第一次在依赖树里看到 babel-runtime/@babel/runtime,很多人会下意识以为它是“又一个 polyfill 包”。但它更像是一套“编译时生成代码的公共工具箱”:把那些会重复出现在每个文件里的 helper 抽出来复用,减少产物体积;同时也能在需要时避免直接往全局对象上打补丁。

什么是 Babel Runtime?

Babel Runtime 可以理解成 Babel 的“运行时配套包”,主要做两件事:

  • 复用 helper:比如 class 继承、对象展开、async/await 的一些辅助逻辑。如果每个文件都内联一份 helper,bundle 里会出现大量重复代码。
  • (可选)避免全局污染:有些能力如果靠 polyfill,会往全局(比如 PromiseArray.prototype)上“补方法”。做业务项目通常问题不大,但写 SDK/组件库时就很容易和别人的环境打架。

通常它会和 transform runtime 插件一起用:编译阶段把“内联 helper”替换成“从 runtime 包里 import”。

说明:Babel 7 里对应的包名是 @babel/runtime@babel/plugin-transform-runtime;老版本 Babel 6 才是 babel-runtime / babel-plugin-transform-runtime。下面用 Babel 7 的写法。


为什么需要 Babel Runtime?

1. 减少重复代码,降低打包体积

如果不使用 runtime 插件,Babel 往往会把 helper 直接塞进每个文件里。模块一多,重复就很明显。

引入 runtime 后,一般会变成:

  • 辅助函数被抽离到 babel-runtime 模块中,所有模块共享同一份代码。
  • 打包工具(如 Webpack、Rollup)能够更好地进行 tree-shaking 和代码优化,进一步减小 bundle 大小。

2. 避免全局作用域污染

传统 polyfill 的做法是“补全环境能力”,实现上经常需要改全局对象。业务项目里你可能感受不深,但做库/组件时这就很敏感:你没法控制用户的运行环境,也不想替别人改全局。

  • 相关 polyfill(例如 core-js)以模块化的方式引入,不会直接修改全局对象。
  • 提高了代码的可维护性和兼容性,尤其适合开发类库或插件时避免副作用。

3. 改善库开发体验

写第三方库时,最怕两件事:产物里重复 helper 导致体积变大;以及无意间污染全局导致“在我这没问题,在用户那炸了”。

  • 库开发者可以确保在编译后的代码中只依赖模块化的辅助函数,而不是全局变量。
  • 使用者在项目中引入库时,不会因为库内部重复的辅助代码而引入额外的冗余。

如何使用 Babel Runtime?

最常见的用法就是:装 runtime 包 + 开 transform runtime 插件。

1. 安装依赖

1
2
npm install --save @babel/runtime
npm install --save-dev @babel/plugin-transform-runtime

2. 配置 Babel

在 Babel 的配置文件(例如 .babelrcbabel.config.js)中添加以下配置:

1
2
3
4
5
6
7
8
9
{
"plugins": [
["@babel/plugin-transform-runtime", {
"helpers": true,
"regenerator": true,
"corejs": false
}]
]
}

配置说明

  • helpers:开启后,Babel 会将内联辅助函数替换为对 babel-runtime 的引用。
  • regenerator:针对 async/await 语法的转换,避免重复引入 regeneratorRuntime。
  • corejs:如果你想让 runtime 以“模块方式”提供 polyfill,可以配置为 2/3,同时安装对应的 runtime(例如 @babel/runtime-corejs3)。不需要的话保持 false 就行。

3. 编写现代 JavaScript 代码

当你在代码中使用例如 async/await、扩展运算符、class 等现代语法时,Babel 会自动将它们转译为兼容性更好的代码,同时引用 babel-runtime 中的辅助函数。这样,你的代码既能兼容低版本浏览器,又能保持模块化和高效的代码结构。


总结

一句话总结:Babel Runtime 负责提供“可复用的 helper /(可选)模块化 polyfill”,而 transform runtime 插件负责把编译产物改成去引用它。

  • 代码复用:避免了重复注入辅助代码,减少了包体积。
  • 全局隔离:采用模块化方式引入 polyfill 和辅助函数,防止全局命名空间污染。
  • 库开发利器:为第三方库提供更干净、模块化的编译结果,降低对全局变量的依赖。

平时如果你看到产物里 helper 重复很多、或者正在做库/组件发布,优先考虑把 runtime 跑起来,收益通常都比较稳定。

Happy Coding!