有没有办法让browserify模块访问全局范围(窗口对象)?

时间:2017-03-31 17:52:29

标签: javascript node.js browserify commonjs

情景

我正在使用Browserify(或类似导入的NodeJS / CommonJS)来要求一些JavaScript库。但是,我很难让他们玩得很好,因为显然Browserify默认拒绝全局范围访问所有模块。例如,这样做不起作用;

file1.js

require('moment');

file2.js

moment(new Date()); // throws moment is undefined

但这可以通过将 file1.js 的内容更改为以下内容来实现;

window.moment = require('moment');

问题

到目前为止,这已经足够好了,但是现在我无法加载时刻时区库(MomentJS的扩展)。 Moment Timezone的文档暗示这两个脚本应该在窗口全局范围内运行,方法是将它们添加为脚本标记,如此;

<script src="moment.js"></script>
<script src="moment-timezone-with-data.js"></script>

所以他们可以像这样使用;

moment().tz("America/Los_Angeles").format();

然而,这似乎很难实现,因为如果我尝试以下内容;

window.moment = require('moment');
require('./../../node_modules/moment-timezone/builds/moment-timezone-with-data-2010-2020'); // the location of my moment-timezone library

我收到运行时错误,指出moment.tz is undefined(意味着第二个库未使用全局范围运行)。如果我尝试将window.moment添加到第二行代码中,我将重写完整库的第一个实例。

所以,简而言之;

有没有办法允许某些Browserify导入具有全局范围访问权限,或者以window对象作为其范围运行?

我知道这有安全隐患,但有选择地使用,这将非常有用,同时需要像需要全局访问权限的JavaScript库那样正确设置自己。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

将小型库放入vendor.js,在<script>的页面上包含该库,使用browserifybrowserify-shim知道它们,并在模块中使用require('libname')

较大的库可能包含在供应商CDN中,也可以通过browserify-shim与browserify相关联。

<强>的index.html

<html>
    <head>
        <script src="vendor.js"></script>
        <script src="bundle.js"></script>
    </head>
    <body>
        Open devtools and inspect the output
    </body>
</html>

<强>的package.json

{
  "scripts": {
    "build": "cat vendor1.js vendor2.js > dist/vendor.js && cp index.html dist/index.html && browserify index.js -o dist/bundle.js"
  },
  "browserify-shim" : {
    "vendor1" : "global:vendor1",
    "vendor2" : "global:vendor2"
  },
  "browserify" : {
    "transform" : [ "browserify-shim" ]
  },
  "devDependencies": {
    "browserify": "^14.1.0",
    "browserify-shim": "^3.8.14"
  },
  "dependencies": {
    "moment": "^2.18.1",
    "moment-timezone": "^0.5.11"
  }
}

有关上述package.json的几点注意事项:

  • 构建:构建应用程序&#39;在dist文件夹中,创建以下结构:
    • DIST
      • 的index.html
      • bundle.js
      • vendor.js
  • &#34; browserify&#34;条目:它只是添加了browserify-shim
  • &#34; browserify-垫片&#34; entry:它告诉browserify vendor1vendor2可用作window(全局)对象的属性。 Browserify不会尝试捆绑它们,require()只会返回这些属性。您需要确保它们实际可用(因此上面的index.html包含<script src="vendor.js">

<强> index.js

var momentfromnpm = require('moment-timezone');
var vendor1 = require('vendor1');
var vendor2 = require('vendor2');
console.log("Hello");
console.log("Using module from npm", momentfromnpm().tz("Europe/London").format());
console.log("using a function from vendor1.js (bundled into vendor.js)", vendor1());
console.log("using a 'module' from vendor2.js (bundled to vendor.js)", vendor2.doWork());

<强> vendor1.js

window.vendor1 = function() { // could also be just `function vendor1()...`
    return "I'm a simple function, defined on a window";
};

<强> vendor2.js

var vendor2 = { // could also be window.vendor2
    doWork: function() {
        console.log("vendor2 doing work");
    }
};

答案 1 :(得分:1)

按照website

的说明安装moment-timezone软件包
npm install moment-timezone --save

file1.js 中,将window.moment定义为:

window.moment = require('moment-timezone/builds/moment-timezone-with-data-2010-2020');

这应该允许您在 file2.js

中使用moment().tz()