commonjs项目迁移到esm需替换require/module.exports为import/export、配置构建工具支持esm、处理cjs包兼容性,并在package.json中设"type":"module"或使用.mjs后缀。

将 CommonJS 项目迁移到 ES Module(ESM)是单页应用(SPA)现代化重构中的关键一步,核心在于模块系统替换、构建工具适配和运行时兼容性处理。迁移本身不难,但需注意语法差异、循环依赖、第三方包兼容性等细节。
明确模块系统差异,统一代码写法
CommonJS 使用 require() 和 module.exports,ESM 使用 import 和 export。二者语法不互通,不能混用(Node.js 的动态 import() 是例外)。迁移前需逐文件替换:
- 把
const utils = require('./utils');改为import utils from './utils.js';(注意:ESM 中路径必须带扩展名,如.js) - 把
module.exports = { fn };改为export { fn };或export default { fn }; - 默认导出与具名导出要匹配:若原 CJS 是
module.exports = class A {},对应 ESM 应用export default class A {};若导出多个值,优先用具名导出 + 解构导入
配置构建工具支持 ESM 输出与解析
Webpack、Vite、Rollup 等现代构建工具默认支持 ESM,但需检查配置是否启用:
- Vite:开箱即用,只需确保
package.json中有"type": "module",或文件后缀为.mjs - Webpack:5+ 版本原生支持 ESM,确认
experiments.outputModule: true(用于生成 ESM 格式 bundle),且resolve.extensions包含'.js' - 若使用 TypeScript,
tsconfig.json中"module"设为"ESNext","moduleResolution"设为"Bundler"(推荐)或"NodeNext"
处理第三方 CommonJS 包的兼容问题
很多 npm 包仍发布为 CommonJS(CJS),在 ESM 环境中直接 import 可能报错或行为异常。应对策略包括:
- 优先使用已提供 ESM 版本的包(查看包的
package.json是否含"exports"字段或"type": "module") - 对纯 CJS 包(如早期版本的
lodash),可通过构建工具自动转换:Webpack 的resolve.fullySpecified: false+defaultExtension,或 Vite 的optimizeDeps.include触发预构建 - 避免直接
import * as xxx from 'xxx'引入 CJS 模块;改用动态import('xxx').then(...)或按需引入(如import debounce from 'lodash/debounce.js')
升级 Node.js 环境与浏览器支持策略
ESM 在 Node.js 12+ 原生支持,但需显式声明。浏览器端则依赖 <script type="module"></script>:
- 在
package.json中添加"type": "module",使所有.js文件按 ESM 解析(此时require不可用) - 若需渐进迁移,可保留部分 CJS 文件,用
.cjs后缀,并在package.json中设置"main": "index.cjs","exports": { ".": "./index.js" } - SPA 的 HTML 入口需将 script 标签改为
<script type="module" src="/src/main.js"></script>,否则浏览器不执行 ESM 逻辑
不复杂但容易忽略。重点不是一次性改完所有 require,而是建立 ESM 约定、验证构建链路、分批替换并测试运行时行为。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











