es modules 迁移需分阶段渐进实施:先配置环境与模块类型,再建桥接层兼容 commonjs,接着从低风险模块开始替换导出语法,最后封装全局状态并验证功能。

老旧项目迁移到 ES Modules(ESM)不是一次性重写,而是分阶段、可验证、不影响现有功能的渐进过程。关键在于“兼容并存”,让新旧模块系统共存,逐步替换,而不是强行切换。
第一步:确认环境与基础配置
Node.js 项目需满足最低版本要求(≥14.18 或 ≥16.0),并在 package.json 中明确声明模块类型:
- 添加 "type": "module" —— 启用 ESM 默认解析规则(
.js文件按 ESM 处理) - 若暂不统一全项目为 ESM,可用 .mjs 扩展名标识新模块文件,避免破坏原有 CommonJS 逻辑
- 检查构建工具(如 Webpack、Vite、Rollup)是否启用 ESM 输入支持;浏览器环境需确保 HTML 中 script 标签带 type="module"
第二步:建立混合加载桥接层
旧代码中大量使用 require() 和 module.exports,不能直接删改。应先封装适配器,让 ESM 可安全导入 CommonJS 模块:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 在 ESM 文件中,
import config from './config.cjs'是合法的(Node.js 自动处理 CJS → ESM 转换) - 对含副作用的 CJS 模块(如初始化全局状态),用
await import('./legacy-init.cjs')动态导入,控制执行时机 - 避免反向操作:ESM 文件不能被
require()同步加载,如必须调用,改用await import('./new-utils.js')
第三步:从高价值低风险模块开始迁移
优先选“纯逻辑、无副作用、依赖少”的模块切入,例如工具函数库、校验方法、格式化工具:
- 将
utils.js重命名为utils.mjs或保持.js但加上"type": "module" - 把
module.exports = { formatDate, deepClone }改为export { formatDate, deepClone } - 在老文件中用
import { formatDate } from './utils.js'替代const { formatDate } = require('./utils'),验证行为一致 - 借助 TypeScript 或 JSDoc 补全类型,提升迁移过程中的可读性与安全性
第四步:处理全局变量与隐式状态
老旧项目常把数据挂到 window、global 或自定义全局对象上,这是模块化的最大障碍:
- 识别所有全局挂载点(如
window.API_BASE_URL、global.userStore),列出访问和修改位置 - 新建 ESM 模块(如
env.js、store.js),用export const API_BASE_URL = '...'和export class UserStore封装 - 通过单例或顶层
export let instance+ 初始化函数,替代裸全局赋值,确保模块内状态可控 - 旧代码中仍读写全局变量?先不动,加一层“防腐层”模块导出兼容接口,后续再逐步替换调用方
不复杂但容易忽略:每次迁移一个模块后,务必运行原有测试用例或手动验证核心路径,确保输出、副作用、时序未变。模块化不是目的,是让代码更可读、可测、可维护的手段。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










