本文将指导你发布双模式、跨运行时的 JAVAScript 包。了解如何创建与 ESM 和 CommonJS 以及 Node.js、Deno 和浏览器等不同运行时兼容的库。
随着 JavaScript 开发的不断发展,人们越来越需要能在多种环境中运行的强大依赖包。在本文中,我们将探讨如何发布跨运行时、双模式的 JavaScript 包。这些包弥补了 ESM 和 CommonJS 之间的差距,让开发人员可以在任何环境下使用相同的包和文档。
在深入了解之前,让我们先熟悉一些关键概念:
双模式包旨在与多个 JavaScript 模块系统(尤其是 ES Modules (ESM) 和 CommonJS (CJS))配合使用。这确保了代码在各种环境中的可重用性和灵活性。创建双模式包有几个好处:
不过,双模式并不能保证软件包在不同的运行环境下都能正常工作,这就带来了以下问题:
跨运行时包可在 Deno、浏览器和 Node.js 等多种环境中运行。它们旨在为不同运行时提供一致的 API。一个全面的跨运行时包应同时支持 ESM 和 CJS,尤其是因为 Node.js 在很大程度上仍在使用 CommonJS。
如果我们忽略 Node.js 的传统限制(Node.js 严重依赖 CommonJS),我们可以只使用 ES 模块构建跨运行时包。这将简化包,但会限制其与旧版 Node.js 项目的兼容性。
你有两种主要方法:从 Deno 或 Node.js 开始。Deno 优先方法使用 Deno 的内置工具和 Deno 到Node工具(DNT)。另一方面,Node优先方法使用传统的构建工具来完成测试、检查和打包等任务。这种方法是转换现有 NPM 库的首选。
Deno优先方法依赖于DNT,你可以在Github[1]上找到。
该工具通过版本库中的自定义构建脚本使用。
第一步是建立一个基本的 Deno 库,准备发布到 deno.land/x。之后,你就可以使用 DNT 了。
「添加脚本」
Deno优先方法的核心是构建流程。下面这个名为 scripts/build_npm.ts 的脚本使用 DNT 创建一个 /npm 文件夹,其中包含一个完整的 NPM 包,可以随时发布。
该脚本将处理清除 NPM 目录、复制测试数据和构建软件包等任务。它还会创建一个完整的 package.json 文件。
让我们一起来看看吧,请务必阅读注释。
import { build, copy, emptyDir } from "./deps.ts";
// Clear NPM directory
awAIt emptyDir("./npm");
// (optional) Copy test data, if you have some
// await copy("tests/data", "npm/esm/tests/data", { overwrite: true });
// This assumes that the entrypoint of your module is ./mod.ts
await build({
entryPoints: ["./mod.ts"],
outDir: "./npm",
shims: {
deno: "dev",
},
/*
mAppings: {
"<https://deno.land/x/zipjs@v2.7.17/index.js>": {
name: "@zip.js/zip.js",
version: "^2.7.17"
},
},
*/
package: {
// package.json template
name: "my-library-name",
version: Deno.args[0],
description: "My library description.",
license: "MIT",
repository: {/* ... */},
author: "You <your@mail>",
/* Additional information */
},
});
// (optional) post build steps, you might want to copy some files?
// ---------------------------------------------------------------
// Deno.copyFileSync("LICENSE", "npm/LICENSE");
// Deno.copyFileSync("README.md", "npm/README.md");
// (optional) Add .npmignore
// ---------------------------------------------------------------
// ensure the test data is ignored in the `.npmignore` file
// so it doesn't get published with your npm package, if relevant
/*
await Deno.writeTextFile(
"npm/.npmignore",
"esm/tests/datanscript/tests/datan",
{ append: true },
);
*/
现在,你只需运行 deno run -A scripts/build_npm.ts 0.0.1 来构建 0.0.1 版本的 npm 软件包。所有相关文件都将在 ./npm 中生成。
最后一步是导航到 ./npm 目录,然后运行 npm publish,就可以了!
「使用 deno.json 更新构建管道流」
要记录这一构建步骤,可以修改 deno.json 的task部分,将新的 NPM 构建步骤包括在内。下面是一个设置测试和 NPM 构建的配置示例:
{
/* ... existing configuration ... */
"tasks": {
"test": "deno test tests --allow-read",
"build": "deno run -A scripts/build_npm.ts"
}
}
现在,运行 deno task build 0.0.1 时将生成 npm 包。
或者,你也可以选择Node优先的方法来创建跨运行时包。
第一步是确保你的项目同时支持 ESM 和 CommonJS。这既可以手动完成,也可以使用构建工具来处理。代码库最好是非转译的 javascript 或 typescript,以便 Rollup 或类似工具处理。
让我们以 @hexagon/base64 库为例进行分析。该库使用 Rollup 生成 ESM 和 CommonJS 版本的代码,配置如下:
// rollup.config.js
export default [
{
input: "./src/base64.single.js",
output: {
file: "dist/base64.cjs",
format: "umd",
name: "base64",
exports: "default"
}
},
{
input: "./src/base64.js",
output: {
file: "dist/base64.mjs",
format: "es"
}
}
];
该库的源代码(/src/base64.js)是以各种方式导出 base64 对象的普通 ES JavaScript。
// src/base64.js
/* ...
Library code making up the base64 object
... */
// Default export
export default base64;
// Named export
export { base64 };
Rollup 无法处理多重导出,因此我还创建了一个 /src/base64.single.js,默认情况下它只负责重新导出 base64 对象。这是 Rollup 配置的 UMD 目标所使用的。
// /src/base64.single.js
import base64 from "./base64.js";
export default base64;
package.json 文件是设置双模式、跨运行时 JavaScript 包的关键。它决定了包在不同环境中的结构和行为方式。让我们来仔细看看其中的关键部分及其重要性:
{
/* ... your metadata ... */
"scripts": {
/* ... your existing build steps ... */
"build:dist": "rollup -c ./rollup.config.js",
},
"type": "module",
"main": "./dist/base64.cjs",
"browser": "./dist/base64.min.js",
"module": "./src/base64.js",
"types": "types/base64.single.d.ts",
"exports": {
".": {
"import": "./src/base64.js",
"require": "./dist/base64.cjs",
"browser": "./dist/base64.min.js"
}
}
}
根据包的具体需求和配置,你可能需要对 package.json 进行或多或少的修改。仔细调整和测试该文件以确保其在发布时正常运行至关重要。
前面提到的步骤主要是在 Node.js 中设置双模式兼容性。虽然 Deno 可以使用开箱即用的 npm 软件包,但要创建一个完整的跨运行时包,你还应该将其适配到 Deno。
这包括阅读 Deno 库的工作原理[2]、将软件包发布到 deno.land/x[3]。
还有就是,让你的软件包成为双模式软件也能帮助其他项目。
创建双模式、跨运行时的 JavaScript 包是一种有益的体验。它能使你的代码具有可移植性和可重用性,让你在不同的 JavaScript 环境中接触到更多的用户。虽然会有一些障碍和注意事项,如管理兼容性以及与不同模块系统和运行时的配合,但利大于弊。
本文译自:https://hexagon.56k.guru/posts/dual-mode-cross-runtime-packages/
以上就是本文的全部内容,如果对你所有帮助,欢迎点赞、收藏、转发~
[1]GitHub:https://github.com/denoland/dnt
[2]Deno 库的工作原理:https://deno.land/manual@v1.36.4/introduction
[3]将软件包发布到 deno.land/x:https://deno.land/manual@v1.36.4/advanced/publishing