Node.js + TypeScript 项目迁移 ESM 记录
2025年8月07日·Hangzhou
Tech
摘要
最近把一个 Node.js + TypeScript 项目从 CommonJS 迁移到了 ESM,整个过程其实没有想象中复杂,记录一下。
# 为什么迁移
以前项目基本都是 CommonJS:
JavaScript
随着 Node.js 对 ESM 的支持越来越完善,以及越来越多的库开始优先支持 ESM,经常会遇到类似的问题:
Shell
例如我用到的一些库:
- got
- playwright
这些库的新版本都更偏向 ESM。
另一方面,现在前端项目几乎全部都是:
JavaScript
既然前后端都在使用 JavaScript,统一到同一种模块规范会更加自然。
# 修改 package.json
首先增加:
JSON
开启后,Node.js 会把 .js 文件按照 ESM 方式解析。
# 修改 TypeScript 配置
这是我认为最重要的一步。
原来的配置:
JSON
修改为:
JSON
完整示例:
JSON
这样 TypeScript 才会按照 Node.js 当前的 ESM 规则解析模块。
# 修改导入方式
原来:
TypeScript
修改为:
TypeScript
导出方式:
TypeScript
修改为:
TypeScript
或者:
TypeScript
# 处理 __dirname
这是我唯一踩到的坑。
CommonJS 中:
TypeScript
可以直接使用。
但是 ESM 中不存在。
需要这样处理:
TypeScript
之后即可继续使用:
TypeScript
# 遇到的问题
# 导入路径必须带后缀
例如:
TypeScript
在 ESM 中可能会报错。
需要改成:
TypeScript
即使源码是 .ts,最终运行时仍然需要写 .js。
# 部分老库仍然是 CommonJS
虽然现在大部分库已经兼容 ESM,但仍然会遇到一些只支持 CommonJS 的库。
这种情况下通常需要:
TypeScript
或者动态导入:
TypeScript
具体根据库的导出方式调整。
# 迁移后的感受
最大的变化其实不是性能提升,而是开发体验更加统一。
无论是:
- Next.js
- Node.js
- Playwright
全部都在使用:
TypeScript
不需要在不同项目之间来回切换 CommonJS 和 ESM 的写法。
另外升级依赖时也更省心,不容易再碰到:
Shell
这类问题。
# 总结
对于新的 Node.js + TypeScript 项目,我更推荐直接使用 ESM。
迁移成本并不高,核心改动主要集中在:
- package.json 添加
type: module - tsconfig 修改为
NodeNext - 替换
require - 替换
module.exports - 处理
__dirname
做完这些后,基本就可以顺利运行了。
对于长期维护的项目来说,我认为这是一个值得投入时间完成的升级。
The End➜cd ~/top
