如何编写一个支持每个JavaScript环境(模块系统)的npm包



在过去的几周里,我一直在研究一个实用程序库,现在我想把它发布在npm上供其他人使用。

该库不使用除 commonjs 模块系统之外的任何特定于节点的功能。它是用纯 es6 编写的,没有任何依赖关系。我希望它与前端(vanilla JavaScript,react 等)以及 Nodejs 中的后端兼容。

我已经查了一些关于这个的文章,但他们使用了 babel,webpack 一些谈到了 rollup 和 bower......我只熟悉 babel 和 webpack,但我不知道如何在这个项目中使用它们(但如果需要,我愿意学习这些技术)。

我只需要一些提示,如何从这一点继续前进。请给我一些关于这个话题的建议。

谢谢是提前<3。我非常感谢您在StackOverflow上所做的努力.

低技术解决方案是创建一个变量,该变量在浏览器中加载时提供包脚本提供的完整 API 或 API 终结点。如果需要,将包写入 IIFE 中,以防止包变量污染浏览器的全局地址空间。

此外,测试节点中是否需要脚本作为 commonJS 模块,如果使用 commonJS 钩子导出 API,如果有:

var myAPI = (()=>{
var exports = {}
//...
exports.foo = "foo";
//...
return exports;
})();
// export myAPI if running in node
if( typeof module == "object" && module && module.exports
&& this && this === module.exports
&& typeof require == "function") {
module.exports = myAPI;
}

节点签名中不太为人所知的部分是调用 commonJS 模块时将其this对象设置为module.exports

这种方法是作为无法通过 file://URL运行JS模块的解决方法而开发的 - 如果模块使用限制可以接受,请考虑直接使用JS模块。

虽然知道更复杂的方法来处理更广泛的使用环境,但我还没有看到它们如何工作的描述。如果读者对更好或更通用的解决方案有见解,我欢迎阅读其他答案。


你也可以告诉节点,一个扩展名为.js的JavaScript文件实际上是一个es6模块,

包括
"type": "module",

在项目package.json文件的根 (JSON) 对象中 - 对于包含单个脚本的包,应该只需要这样做。

要在 node 中实际使用模块文件,请确保主应用程序脚本文件已被赋予mjs扩展名(以便它可以使用import语句而不会引发错误),或者在 commonJS 环境中使用导入表达式导入模块。

答案是:使用模块捆绑器,如 webpack、rollup、gulp 等。 将所有模块与UMD模块系统捆绑在一起。

好吧,我花了更长的时间弄清楚并学习所有这些东西,然后我 预期。最后,我有一些空闲时间写它,以防有人发现 它很有用!

我的项目结构

.
├── dist
├── src
│   ├── index.ts
│   ├── interface.ts
│   └── util.ts
├── tests
│   ├── index.test.ts
│   └── util.test.ts
├── package.json
├── tsconfig.json
├── package-lock.json
└── webpack.config.js

我的tsconfig.json文件

{
"compilerOptions": {
"strict": true,
"target": "es5",
"rootDir": "./src",
"outDir": "./dist",
"declaration": true,
"module": "commonjs",
"skipLibCheck": true,
"esModuleInterop": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true
},
"include": ["./src/*"]
}

现在,我们需要将/src目录中的所有模块捆绑到一个 模块index.js/dist目录中。为此,我们将使用一个流行的 称为webpack的模块捆绑器。

但是,如果我们希望每个 JavaScript 环境都支持该捆绑文件。 即,每个JS模块系统(commonJS,ES6,AMD等)然后我们 需要使用 UMD(通用模块) 定义)模块系统。幸运的是,几乎每个模块捆绑器都可以照顾好 的。

安装webpackts-loader(将 TypeScript 转换为 JavaScript) 为 开发依赖项(带有-D选项)。

npm i -D webpack webpack-cli ts-loader

我的webpackts-loader版本

{
"webpack": "^5.65.0",
"ts-loader": "^9.2.6",
"webpack-cli": "^4.9.1",
}

我的webpack.config.js

const path = require("path");
module.exports = {
mode: "production",
entry: "./src/index.ts", // entry point of our project
module: {
rules: [
// use ts-loader to transpile .ts files
{
test: /.ts/,
use: "ts-loader",
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [".ts"],
},
output: {
// empty the output directory on every build
clean: true,
// the dir of output bundle
path: path.resolve(__dirname, "dist"),
// output bundle name
filename: "index.js",
globalObject: "this",
library: {
// your lib name if imported with the <script> tag
// for this library it will be available as `window.char_series`
name: "char_series", 
// the module type
type: "umd",
export: "default",
},
},
};

请参考webpack文档 详细解释。另请阅读他们的 创作库 指导。

要构建(捆绑)这个库,我们可以在终端中运行webpack命令 或者我们可以使用npm 脚本自动执行此过程。

package.json的脚本部分

"scripts": {
"test": "jest",
"build": "webpack",
"prepublishOnly": "npm test && npm run build"
}

在这里,我使用jest进行测试。在我们的package.json我们可以运行npm testnpm run build来测试和构建我们的 项目分别。"prepublishOnly"字段中的命令负责 每次发布项目时都测试和构建项目npm publish.

通过上述配置,我在 npm 上发布了一个名为char-series.在github上看到它。

我希望你觉得这篇文章有用,并感谢阅读。

最新更新