Appearance
目前 Web 开发倾向于
ESM
,Node 开发倾向于CJS
。
模块化的核心包括以下特性,基本都是围绕如何处理文件(模块)。
- 拆分:将代码根据功能拆分为多个可复用模块
- 加载:通过指定方式加载模块并执行与输出模块
- 注入:将一个模块的输出注入到另一个模块
- 管理:因为工程模块数量众多需管理模块间的依赖关系
在 JS 发展历程中,主要有六种常见模块方案,分别 是IIFE、CJS、AMD、CMD、UMD和ESM
。
分析每个模块方案的特性可知,同步加载
包括IIFE
与CJS
,异步加载
包 括AMD
、CMD
和ESM
。浏览器
可兼容IIFE
与AMD
,服务器
可兼 容CJS
,浏览器与服务器
都兼容CMD、UMD和ESM
。
- 运行时加载指整体加载模块生成一个对象,再从对象中获取所需的属性方法去加载。 最大特性是
全部加载
,只有运行时才能得到该对象,无法在编译时做静态优化。 - 编译时加载指直接从模块中获取所需的属性方法去加载。最大特性是
按需加载
,在 编译时就完成模块加载,效率比其他方案高,无法引用模块本身(本身不是对象
),但可 拓展JS
高级语法(宏与类型校验
)。
CJS/ESM 的指定方式:
mjs
文件使用ESM解析
,cjs
文件使用CJS解析
,js 文件使用基于 package.json 指定的 type 解析 (type=commonjs使用CJS
,type=module使用ESM
)。
Node v13.2.0 在默认情况下,会启动对 ESM 的实验支持,无需在命令中加上 --experimental-modules 参数。那 Node 是如何区分 CJS 与 ESM?简而言之,Node 会将 以下情况视为 ESM。
- 文件后缀为
.mjs
- 文件后缀为
.js
且在package.json
中指定type
为module
- 命令中加上
--input-type=module
- 命令中加上
--eval cmd