有没有办法允许 browserify 模块访问全局范围(window 对象)?

Is there a way to allow browserify modules access to the global scope (window object)?

场景

我正在使用 Browserify(或 NodeJS/CommonJS 类似导入)来获取一些 JavaScript 库。但是,我很难让它们发挥出色,因为显然 Browserify 默认情况下拒绝对所有模块进行全局范围访问。例如,这样做是行不通的;

file1.js

require('moment');

file2.js

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

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

window.moment = require('moment');

问题

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

<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 需要全局访问权限的库才能正确设置自己。任何帮助将不胜感激。

将小型库放入 vendor.js,使用 <script> 将其包含在您的页面上,使用 browserify-shimbrowserify 知道它们并使用它们 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:

  • build:它在 dist 文件夹中构建 'application',创建以下结构:
    • 距离
      • index.html
      • bundle.js
      • vendor.js
  • "browserify"条目:它只是添加了browserify-shim
  • "browserify-shim" 条目:它告诉 browserify vendor1vendor2 可用作 window(全局)对象的属性。 Browserify 不会尝试捆绑它们,require() 只会 return 这些属性。您需要确保它们确实可用(因此上面的 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");
    }
};

按照 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()