amd/cmd/commonjs/umd/esm/iife/systemjs
总
为了模块拆分
AMD(asynchromous module definition 异步模块定义)
RequireJS,前端,异步
1 | define('module1', ['jquery'], ($) => { |
CMD(Common Module Definition - 公共模块定义) 有些地方都不再单独提及
CMD是SeaJS在推广过程中对模块定义的规范化产出,对于模块的依赖,CMD是延迟执行
1 | define((require, exports, module) => { |
CommonJS(cjs)
CommonJS服务端,Node.js,同步
使用require / module.exports
file1.js
1 | moudle.exports = { |
file2.js
1 | var f1 = require('./file1'); |
umd(Universal Module Definition - 通用模块定义)
amd(浏览器,异步) 和 commonjs(服务器,同步) 合并
使用诸如Rollup/ Webpack之类的bundler时通常用作备用模块
1 | ((root, factory) => { |
ESM(ECMA Script Modules)
es6 模块化规范 (nodejs新版本可直接用,现代化浏览器script标签加type="module" 可用)
常见的 export / import
1 | // 写法一 |
iife(立即 调用 函数 表达)
A self-executing function suitable for inclusion as a <script> tag. If you want to create a bundle for your application, you probably want to use this.
示例
1 | (function () { |
systemjs
示例
1 | System.register('myBundle', [], function () { |
universal module loader that supports CJS, AMD, and ESM modules
SystemJS is a hookable, standards-based module loader. It provides a workflow where code written for production workflows of native ES modules in browsers (like Rollup code-splitting builds), can be transpiled to the System.register module format to work in older browsers that don’t support native modules, running almost-native module speeds while supporting top-level await, dynamic import, circular references and live bindings, import.meta.url, module types, import maps, integrity and Content Security Policy with compatibility in older browsers back to IE11.
简单说在老的浏览器依然可以跑native module,且效率不差
表格
| amd(requirejs) | cmd | commonjs(cjs) | umd | esm | iife | systemjs |
|---|---|---|---|---|---|---|
| 异步模块定义 | 公共模块定义 | 服务端模块规范 | 通用模块定义 | ecma脚本模块 | 立刻自执行模块 | 系统js??翻译不能? |
| 异步 | 异步 | 同步 | 服务端同步浏览器异步 | es6手动编写,被webpack打包成amd,umd,cjs | 同步立即 | 用于在老浏览器跑其它格式的js module |
| 浏览器 | 相关seajs | 服务器(nodejs), (通过Browserify用于浏览器) | 先判断服务器再浏览器 | 新版nodejs支持,老版本可以用webpack/rollup等打包 | 浏览器script标签 | 浏览器 |
Tree Shaking
rollup 提出
见rollup 的 repl(Read-Eval-Print-Loop) 的在线 tree-shaking 示例, 上面的几种生成转换也是可以在在线的repl上看的
- 只能作为模块顶层的语句出现,不能出现在 function 里面或是 if 里面。(ECMA-262 15.2)
- import 的模块名只能是字符串常量。(ECMA-262 15.2.2)
- 不管 import 的语句出现的位置在哪里,在模块初始化的时候所有的 import 都必须已经导入完成。换句话说,ES6 imports are hoisted。(ECMA-262 15.2.1.16.4 - 8.a)
- import binding 是 immutable 的,类似 const。比如说你不能 import { a } from ‘./a’ 然后给 a 赋值个其他什么东西。(ECMA-262 15.2.1.16.4 - 12.c.3)
切记副作用
总结
上面提到的几种 仅仅是写法示例,完整的书写规则见各自的官方文档,或者下面的参考链接
现代书写来说,基本就是书写esm了,剩下的事情就由 rollup/webpack之类的工具去完成了