Rslib 支持四种 JavaScript 文件的输出格式:esm
、cjs
、umd
和 mf
。在本章中,我们将介绍这些格式之间的区别以及如何为你的库选择合适的格式。
库作者需要仔细考虑支持哪种模块格式。让我们了解一下 ESM (ECMAScript Modules) 和 CJS (CommonJS),以及何时使用它们。
ESM: ESM 是一种在 ES2015 中引入的现代模块系统,允许将 JavaScript 代码组织成可重用的、自包含的模块。ESM 现在是 浏览器 和 Node.js 环境的标准,取代了旧的模块系统,如 CommonJS (CJS) 和 AMD。
CommonJS: CommonJS 是一种在 JavaScript 中使用的模块系统,特别是在像 Node.js 这样的服务器端环境中。它的诞生是为了通过提供一种管理模块和依赖项的方法,允许 JavaScript 在浏览器之外使用。
require()
ESM 脚本;你只能导入 ESM 脚本,像这样:import {foo} from 'foo'
import
语句,如上所示。import
CJS 脚本,但只能使用默认导入语法 import _ from 'lodash'
,而不能使用命名导入语法 import {shuffle} from 'lodash'
,如果 CJS 脚本使用命名导出,这会很麻烦。(不过,有时 Node 会不可预料 地猜出你的意思!)require()
CJS 脚本,即使是命名导出,但通常不值得这样做,因为这需要更多的模板代码,而且最糟糕的是,像 webpack 和 Rollup 这样的打包工具不知道/不会处理使用 require()
的 ESM 脚本。.js
重命名为 .mjs
来选择性开启 ESM 模式。或者,你可以在 package.json
中设置 "type": "module"
,然后通过将脚本从 .js
重命名为 .cjs
来选择性关闭 ESM。(你甚至可以通过在单个子目录中放置一行 {"type": "module"}
package.json
来调整它。)对于不同类型的库,模块格式的选择可能会有所不同。以下是两种常见的情况:
发布纯 ESM 库是现代环境库的最佳选择,例如浏览器应用程序或支持 ESM 的 Node.js 应用程序。然而,如果上游库是 CJS 格式,它们只能通过动态导入使用纯 ESM 库,例如 const pureEsmLib = await import('pure-esm-lib')
。
社区正在向 ESM 迁移,但仍有许多项目在使用 CJS。如果你想同时支持 ESM 和 CJS,可以发布一个双重包。对于大多数库作者来说,提供双重格式是一种更安全、更平滑的方式,可以同时享受两种格式的优点。你可以阅读 antfu 的博客文章 在一个包中发布 ESM 和 CJS 了解更多详情。
优点:
缺点:
UMD 代表 通用模块定义,这是一种编写 JavaScript 模块的模式,可以在不同的环境中通用,例如浏览器和 Node.js。其主要目标是确保与最流行的模块系统兼容,包括 AMD(异步模块定义)、CommonJS(CJS)和浏览器全局变量。
如果你正在构建一个需要在浏览器和 Node.js 环境中使用的库,UMD 是一个不错的选择。UMD 可以作为独立的脚本标签在浏览器中使用,也可以作为 CommonJS 模块在 Node.js 中使用。
StackOverflow 上的详细回答:什么是通用模块定义 (UMD)?
然而,对于前端库,你仍然可以提供一个单一文件,方便用户从 CDN 下载并直接嵌入到他们的网页中。这通常仍然采用 UMD 模式,只是现在不再由库作者手动编写/复制到源代码中,而是由转译器/打包器自动添加。
同样地,对于需要在 Node.js 中运行的后端/通用库,你仍然可以通过 npm 分发一个 CommonJS 模块构建,以支持所有仍在使用旧版 Node.js 的用户(他们不想/不需要自己使用转译器)。这在新库中不太常见,但现有库会尽力保持向后兼容,不会导致应用程序被破坏。
umd
。以下是一个构建 UMD 库的 Rslib 配置示例。
lib.format: 'umd'
: 配置 Rslib 构建 UMD 库。lib.umdName: 'RslibUmdExample'
: 设置 UMD 库的导出名称。output.externals.react: 'React'
: 指定外部依赖 react
可以通过 window.React
访问。runtime: 'classic'
: 使用 React 的 classic 运行时,以支持使用 React 版本低于 18 的应用程序。MF 代表 Module Federation。模块联邦是一种用于 JavaScript 应用程序分解的架构模式(类似于服务器端的微服务),允许你在多个 JavaScript 应用程序(或微前端)之间共享代码和资源。
请参阅 模块联邦 以获取更多详细信息。