
2020 年了,nodejs 和浏览器基本都支持了原生 esm,那么现在 js 库该怎么写?本文先解释他们分别是什么,再结合最新环境支持给出建议和实践。
他们分别是什么?
你可以用 rollup 的在线 repl 来查看各种模块写法
它们是在 JS 里用来实现“模块”的不同规则。
CJS
CommonJS,只能在 NodeJS 上运行,使用 require("module") 读取并加载模块。
缺点:不支持浏览器,执行后才能拿到依赖信息,由于用户可以动态 require(例如 react 根据开发和生产环境导出不同代码 的写法),无法做到提前分析依赖以及 Tree-Shaking 。
AMD
Asynchronous Module Definition,可以看作 CJS 的异步版本,制定了一套规则使模块可以被异步 require 进来并在回调函数里继续使用,然后 require.js 等前端库也可以利用这个规则加载代码了,目前已经是时代的眼泪了。
UMD
Universal Module Definition,同时兼容 CJS 和 AMD,并且支持直接在前端用 <script src="lib.umd.js"></script> 的方式加载。现在还在广泛使用,不过可以想象 ESM 和 IIFE 逐渐代替它。
IIFE
Immediately Invoked Function Expression,只是一种写法,可以隐藏一些局部变量,前端人要是不懂这个可能学的是假前端。可以用来代替 UMD 作为纯粹给前端使用的写法。
ESM
ECMAScript Module,现在使用的模块方案,使用 import export 来管理依赖。由于它们只能写在所有表达式外面,所以打包器可以轻易做到分析依赖以及 Tree-Shaking。当然他也支持动态加载(import())。
浏览器直接通过 <script type="module"> 即可使用该写法。NodeJS 可以通过使用 mjs 后缀或者在 package.json 添加 "type": "module" 来使用,注意他还有一些 实验性的功能 没有正式开启。考虑到大量 cjs 库没有支持,如果要发布 esm 版的库还是通过 rollup 打包一下比较好(同时相关依赖可以放到 devDependencies 里)。
其他
SystemJS
库该怎么写?
其实很简单,要看你需要支持哪些平台:
只支持 NodeJS 的 require 写法
package.json:"main": "index.js",
其中 index.js 使用 cjs 写法(module.exports = xxx;)
只支持 NodeJS 的 import 写法
package.json:"main": "index.mjs" 或 "type": "module", "main": "index.js"
其中 index.mjs 或 index.js 使用 esm 写法(export default xxx)
同时支持 NodeJS 的 require 和 import 写法
利用 条件 export,直接看文档里面有例子。
支持浏览器直接通过 <script> 引入的写法
package.json:"browser": "index.global.js",然后 jsDelivr 等 cdn 会自动使用这个文件,具体到 cdn 上还有 "jsdelivr": "index.jsdelivr.js" 等配置写法,权重更高。
这里可以试试 esbuild 输出 iife 格式的包,比 webpack/babel 更快,除了对 cjs 的库不太友好(可以配合下面 rollup/commonjs 插件使用)。
浏览器直接支持 type="module" 引入 esm 写法的文件,但是这对于 cdn 来说并不友好:cdn 看到 import "xxx" 并不知道如何找到 xxx 模块,所以这种写法建议只在本地使用。另外也可以通过 vite,让它使用 rollup 和 esbuild 帮你引入这些外部模块。
支持现代打包器 rollup 和 webpack2+ 通过 import 引入的写法
package.json:"module": "index.esm.js"
如果某些库没有写这个选项,那么可以借助 rollup 的 commonjs 插件转译到可用,具体做法可以参考 rollup 文档。
如何实践?
完全使用 ESM,如果有不同环境的需求,通过 rollup 打包成支持目标环境的其他格式(esm 给其他打包器使用, iife 给浏览器, cjs 给 nodejs 玩家),可以参考 vue3。
本文探讨2020年后的JavaScript库开发,解析CJS、AMD、UMD、IIFE和ESM模块的区别与应用场景,并给出在不同环境下的最佳实践建议,包括如何利用rollup和esbuild进行打包优化。
1102

被折叠的 条评论
为什么被折叠?



