从同一来源构建分布式和 NPM 包
Build both distributive and NPM package from the same source
我经常做一些开源的小工具,不想限制我的用户。我的包通常只有一个功能,所以这就是我希望我的用户得到的:
- 他们可以通过
script
标签中的 src
添加的 JS 文件。该脚本应该添加我的函数,以便他们可以在下面的脚本中调用它。对根本不想使用包管理器的用户有用:
<script src="https://amazingCDN.com/isEven.js"></script>
<script>
isEven()
</script>
- 一个JS文件,可以打包发布,所以使用npm的用户直接输入
npm install isEven
,然后导入我的包即可。
两个 JS 文件应该从同一个源构建。假设我的源代码只包含一个命名函数,应该添加到 window
并且如果我使用 Webpack 应该是可导入的。假设我将自己发布一个包,我只希望我的构建管道从我的源代码生成两个 JS 文件。 CDN 怎么样,假设我使用 jsDelivr,它可以从 Github 检索我的 JS 文件并缩小它,所以我不关心自己缩小我的文件。
我尝试将我的代码编写为一个模块,并使用带有独立标志的 Browserify。它实际上适用于 CommonJS 模块,但要使其适用于 ES 模块,我必须使用 esmify,它只是 returns 一个带有 default
键的对象,所以我不能像 foo()
,我得把它叫做foo.default()
。这不是我想要的。
我也试过把它写成一个独立的文件,然后就这样做了
echo 'export default ' | paste -d'[=11=]' - src.js > module.js
有点管用,但我想知道是否有更复杂、更可靠的解决方案。
我该如何实现?
听起来您可能想将项目打包为 UMD
Rollup 可以将 UMD 作为输出,并且比 webpack 或 browserify 更小(特别是对于微小的单一函数库)
isEven.mjs
function isEven(x) {
return (x % 2) === 0 && x !== 0;
}
export {
isEven
};
$ rollup isEven.mjs --format=umd --name=isEven
将导致
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.isEven = {}));
}(this, (function (exports) { 'use strict';
function isEven(x) {
return (x % 2) === 0 && x !== 0;
}
exports.isEven = isEven;
Object.defineProperty(exports, '__esModule', { value: true });
})));
我认为这正是您想要的。
我解决了这个问题并为这个任务创建了一个模板库。
您可以从这个模板创建您的 repo,将您的库实现为带有 ES 模块的 NPM 包,然后在推送时将创建 dist 文件夹,并且会有以您的库命名的分布式 js 文件。您的用户只需将它添加到脚本标签中,您的库就会出现在全局命名空间中。
我经常做一些开源的小工具,不想限制我的用户。我的包通常只有一个功能,所以这就是我希望我的用户得到的:
- 他们可以通过
script
标签中的src
添加的 JS 文件。该脚本应该添加我的函数,以便他们可以在下面的脚本中调用它。对根本不想使用包管理器的用户有用:
<script src="https://amazingCDN.com/isEven.js"></script>
<script>
isEven()
</script>
- 一个JS文件,可以打包发布,所以使用npm的用户直接输入
npm install isEven
,然后导入我的包即可。
两个 JS 文件应该从同一个源构建。假设我的源代码只包含一个命名函数,应该添加到 window
并且如果我使用 Webpack 应该是可导入的。假设我将自己发布一个包,我只希望我的构建管道从我的源代码生成两个 JS 文件。 CDN 怎么样,假设我使用 jsDelivr,它可以从 Github 检索我的 JS 文件并缩小它,所以我不关心自己缩小我的文件。
我尝试将我的代码编写为一个模块,并使用带有独立标志的 Browserify。它实际上适用于 CommonJS 模块,但要使其适用于 ES 模块,我必须使用 esmify,它只是 returns 一个带有 default
键的对象,所以我不能像 foo()
,我得把它叫做foo.default()
。这不是我想要的。
我也试过把它写成一个独立的文件,然后就这样做了
echo 'export default ' | paste -d'[=11=]' - src.js > module.js
有点管用,但我想知道是否有更复杂、更可靠的解决方案。
我该如何实现?
听起来您可能想将项目打包为 UMD
Rollup 可以将 UMD 作为输出,并且比 webpack 或 browserify 更小(特别是对于微小的单一函数库)
isEven.mjs
function isEven(x) {
return (x % 2) === 0 && x !== 0;
}
export {
isEven
};
$ rollup isEven.mjs --format=umd --name=isEven
将导致
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.isEven = {}));
}(this, (function (exports) { 'use strict';
function isEven(x) {
return (x % 2) === 0 && x !== 0;
}
exports.isEven = isEven;
Object.defineProperty(exports, '__esModule', { value: true });
})));
我认为这正是您想要的。
我解决了这个问题并为这个任务创建了一个模板库。
您可以从这个模板创建您的 repo,将您的库实现为带有 ES 模块的 NPM 包,然后在推送时将创建 dist 文件夹,并且会有以您的库命名的分布式 js 文件。您的用户只需将它添加到脚本标签中,您的库就会出现在全局命名空间中。