为什么需要模块?
模块化让代码组织更好,可维护性强。
CommonJS
Node.js 使用。
1 | // module.js |
ES6 Modules
现代标准。
1 | // module.js |
默认导出
1 | // module.js |
动态导入
1 | import('./module.js').then(module => { |
模块加载
浏览器
1 | <script type="module" src="main.js"></script> |
Node.js
1 | // package.json |
工具支持
- Webpack
- Rollup
- Vite
总结
ES6 Modules 是未来趋势。支持静态分析,Tree Shaking 等优化。逐渐替代 CommonJS。
其他模块规范
AMD (Asynchronous Module Definition)
适用于浏览器环境,支持异步加载:
1 | define(['dep'], function(dep) { |
UMD (Universal Module Definition)
兼容 CommonJS、AMD 和全局变量,常见于库发布。
1 | (function (root, factory) { |
SystemJS
一个动态加载模块的加载器,可在浏览器和 Node 中使用。
模块打包工具
- Webpack:默认支持 ES modules,使用
import语法。 - Rollup:专注于库打包,支持 Tree Shaking。
- Parcel/Vite:零配置,内置 ESM 支持。
- Babel:可以将 ES6 模块转换为 CommonJS,以兼容旧环境。
模块加载流程
- 解析依赖树
- 下载/读取模块
- 执行模块代码
- 缓存模块结果
静态导入在编译阶段解析,动态导入在运行时加载。
模块性能与优化
- 采用 ES modules 可减少打包体积
- 使用
import()做懒加载 - 合理拆分代码,避免重复依赖
- 利用浏览器原生缓存
兼容性问题
| 功能 | 浏览器 | Node.js |
|---|---|---|
静态 import |
支持(script type=“module”) | 需配置 |
动态 import() |
支持 | 支持 |
| 默认导出 interop | 需要 Babel 处理 | 自动兼容 |
迁移策略
- 逐步将 CommonJS 文件改为 ES modules
- 使用工具(
cjs-to-esm,babel-plugin-transform-modules-commonjs) - 在 package.json 中添加
"type": "module"或使用.mjs扩展名
未来发展
随着浏览器和 Node 原生支持的普及,模块系统会变得更加统一。标准委员会还在研究模块的加载规范和安全性增强。
附录
- 模块与命名空间
- 全局变量污染问题
- 使用 webpack 的
externals配置避免重复打包