配了八年 Babel,今天才发现它悄悄把整个构建链换了——ESM-only 这件事,账全变了
配了八年 Babel,今天才发现它悄悄把整个构建链换了——ESM-only 这件事,账全变了
上周升级了一个老项目的依赖,手滑把 @babel/core 升到了最新版。跑构建的时候直接崩了,报了一堆 require(esm) 的错误。翻了半天才发现——Babel 8 两个月前发布了,而且这次改得比以往任何一次都狠。
八年了,Babel 终于对自己动了刀。
下载量从 170 万到 6.51 亿,但这次不是加功能
Babel 8 是 2026 年 6 月 16 日正式发布的,距离 Babel 7 正好八年。这八年里,SWC 和 Oxc 先后冒出来,Rust 系的编译器在速度上已经领先 Babel 几个量级。但有意思的是,Babel 的周下载量反而从 2018 年的 170 万涨到了现在的 6.51 亿——翻了三番。
所以 Babel 8 的定位很清楚:不加新功能,动刀子清理历史债务,为下一个八年做准备。
三个最大的变化,每一个都是 breaking change。
第一个:ESM-only,Node.js 24+ 才能跑
Babel 8 现在只发布原生 ESM 模块,不再提供 CommonJS 构建。如果你还在用 require("@babel/core") 这种写法,构建直接报错。Node.js 版本要求也提升了——需要 24 或 26,22 和 25 已经停止维护,不再受支持。
这意味着,如果你还在用老版本的 CI 镜像或者 Docker 基础镜像,第一步就得先升级 Node.js。迁移路径倒是有:Babel 8 支持通过 require(esm) 做 CJS 和 ESM 混合导入,但这只是过渡方案,不建议长期依赖。
第二个:不再默认编译到 ES5,默认目标变成 ES2023
这是影响最广的变化。Babel 7 默认编译到 ES5,意味着你要兼容 IE11 也完全没问题。但 Babel 8 的 @babel/preset-env 不再默认输出 ES5 了,改成依赖 Browserslist 的 defaults 查询——当前默认值大约是 ES2023 水平。
换句话说,如果你不主动配置 targets,Babel 8 会假设你的代码运行在现代浏览器上,不再做 ES5 转译。好处是 bundle 体积会明显缩小,因为像 const/let、箭头函数、async/await 这些 ES6+ 特性不用再被转译成 ES5 了。但坏处是——如果你真的有兼容老浏览器需求,升级之后代码直接白屏。
配合这个变化,Babel 8 的默认输出格式也从 CommonJS 切换到了 ESM。所以如果你用 module.exports 的方式消费 Babel 输出,也要改成 ESM 的 export。
第三个:loose/spec 选项废除,改用 assumptions
Babel 以前有 loose 和 spec 两个选项,用来控制转译是更贴合规范还是更省代码体积。这两个选项在 @babel/preset-env 里被彻底移除了,单独插件里虽然还保留但已经 deprecated。
接替它们的是一个更细粒度的机制:assumptions。assumptions 是顶层配置项,可以针对你的代码库统一设定一组假设,比如”我确定我的代码不会传给 eval 执行”、”我确定没有继承原生类的子类”——每个 assumption 都是一个布尔值,粒度更细,语义更清晰。
这个变化对普通用户影响不大,但如果你用了 loose: true 模式做输出优化,升级后要重新对标 assumptions 配置。
**内置 TypeScript 类型,不用再装 @types/babel__***
这是个小但实用的改进。Babel 8 所有官方包现在都内置了 TypeScript 类型定义,不用再单独安装 @types/babel__* 系列包了。如果你用 Babel 的 programmatic API 做插件开发或者自定义构建步骤,这一点会省不少事。
迁移其实没那么难,但准备工作要做
Babel 团队自己也说了——Babel 5 到 6、Babel 6 到 7 的升级都有人骂,但这次 7 到 8 的迁移会简单得多。官方提供了详细的迁移指南和 codemod 工具,建议先在分支上跑一遍,确认没问题再合入主分支。
关键检查项:
第一步先升级 Node.js 到 24+,因为 Babel 8 跑不起来;第二步把 babel.config.js 改成 babel.config.mjs 或者在 package.json 里加 "type": "module",因为配置本身也要是 ESM;第三步如果你的 targets 原来没配,现在要补上,因为默认行为变了;第四步检查插件的 peerDependencies,确保 @babel/core@^8 被正确声明;第五步如果用了 @babel/plugin-proposal-* 系列插件,它们已经被重命名成 @babel/plugin-transform-* 了,这个改写在 Babel 7.22 就完成了,现在只是正式收口。
你的项目要不要马上升级?
如果你的项目还在跑 Babel 7,构建正常,也不是不能等等看——Babel 7 的最后一个版本 7.29.0 会维护到 2027 年中。但如果你用到了 Vite 8+ 或者其他已经做了 Babel 8 适配的工具链,越早升越好,因为插件生态会逐步切到 ESM-only,不升级的插件迟早会断开连接。
这次升级的本质,是 Babel 在倒逼整个前端生态把 ESM 这件事彻底做完整。八年前 Babel 7 出来的时候,CommonJS 还是主流;现在 ESM 已经是 Node.js 的默认模式,Babel 跟上了这个节奏。
你的构建链,准备好了吗?
评论区
登录后可评论。