假设我正在用 JavaScript 编写一个模块,它可以在浏览器和服务器(使用 Node)上使用。让我们称之为模块。假设 Module 将受益于另一个名为 Dependancy 的模块中的方法。这两个模块都被编写为供浏览器和服务器使用,就像 CommonJS 风格:
module.js
if (typeof module !== 'undefined' && module.exports)
module.exports = Module; /* server */
else
this.Module = Module; /* browser */
dependancy.js
if (typeof module !== 'undefined' && module.exports)
module.exports = Dependancy; /* server */
else
this.Dependancy = Dependancy; /* browser */
显然,Dependancy 可以直接在浏览器中使用。但是如果 Module 包含一个 var dependancy = require('dependency');
指令,“维护”模块变得更加麻烦。
我知道我可以对 Module 中的Dependancy 进行全局检查,如下所示:
var dependancy = this.Dependancy || require('dependancy');
但这意味着我的模块有两个额外的浏览器安装要求:
- 用户必须将 dependency.js 文件包含在
<script>
中在他们的文档中 - 并且用户必须确保在 module.js 之前加载此脚本
添加这两个要求引发了像 CommonJS 这样易于使用的模块化框架的想法。
我的另一个选择是在我的 Module 包中包含第二个编译脚本,其中包含 dependency.js
使用 browserify 捆绑.然后我指示在浏览器中使用脚本的用户包含此脚本,而服务器端用户使用 package.json
中概述的未捆绑的入口脚本。 .这比第一种方式更可取,但它需要一个预编译过程,我每次更改库时都必须运行这个过程(例如,在上传到 GitHub 之前)。
还有什么我没有想到的其他方法吗?
最佳答案
当前给出的两个答案都非常有用,并且帮助我得出了当前的解决方案。但是,根据我的评论,它们并不能完全满足我对可移植性和易用性的特殊要求(对于客户和模块维护者)。
我最后发现的是 browserify 中的一个特定标志。可以捆绑模块并将它们公开为全局变量并在 RequireJS 中使用(如果需要)的命令行界面。 Browserify(和其他人)称之为通用模块定义(UMD)。关于那个的更多信息here .
通过在 browserify 命令中传递 --standalone
标志,我可以轻松地为 UMD 设置我的模块。
所以...
这是模块的package.js
:
{
"name": "module",
"version": "0.0.1",
"description": "My module that requires another module (dependancy)",
"main": "index.js",
"scripts": {
"bundle": "browserify --standalone module index.js > module.js"
},
"author": "shennan",
"devDependencies": {
"dependancy": "*",
"browserify": "*"
}
}
因此,当处于我的模块的根目录时,我可以在命令行中运行它:
$ npm run-script bundle
它将依赖项捆绑到一个文件中,并按照 UMD 方法公开它们。这意味着我可以通过三种不同的方式引导模块:
NodeJS
var Module = require('module');
/* use Module */
浏览器 Vanilla
<script src="module.js"></script>
<script>
var Module = module;
/* use Module */
</script>
带有 RequireJS 的浏览器
<script src="require.js"></script>
<script>
requirejs(['module.js'], function (Module) {
/* use Module */
});
</script>
再次感谢大家的意见。所有答案都是有效的,我鼓励大家尝试所有答案,因为不同的用例需要不同的解决方案。
关于javascript - 打包具有依赖项的浏览器/服务器 CommonJS 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36454785/