generator函数转译会因regenerator-runtime注入大量辅助代码导致体积膨胀100–500 kb;可通过升级targets禁用插件、external+cdn外链或usebuiltins: 'usage'按需注入来优化。

Generator 函数(function*)在编译为 ES5 时,Babel 默认会通过 @babel/plugin-transform-regenerator 插件将其转译为基于 regenerator-runtime 的状态机实现。这个过程会注入大量辅助代码(如 runtime.js 中的 mark、wrap、awrap、async 等函数),一旦项目中多处使用 yield 或 async/await(后者底层也依赖 regenerator),这些辅助逻辑就会被重复打包或全局引入,导致体积显著增加——常见膨胀 100–300 KB,极端项目甚至引入 500 KB+ 的 runtime。
确认是否真由 regenerator 引起体积膨胀
先定位问题根源,避免误优化:
- 用
webpack-bundle-analyzer或rollup-plugin-visualizer分析产物,搜索关键词regenerator、runtime、mark、wrap,查看是否集中在node_modules/regenerator-runtime或内联的 Babel runtime helper 中 - 检查
babel.config.js是否启用了@babel/plugin-transform-regenerator(尤其在未配置 targets 且需兼容 IE11 时,Babel 会默认启用) - 运行
npx babel --list-envs查看当前 preset-env 推导出的 target,若包含ie:11或chrome ,则大概率触发 regenerator 插件自动注入
优先升级运行时环境,直接禁用 regenerator
绝大多数现代项目已无需支持 IE 或老旧安卓 WebView。只要目标环境支持原生 async/await 和 generator(Chrome 55+/Firefox 52+/Safari 10+/Edge 15+),就可完全跳过 regenerator 转译:
- 在
babel.config.js中明确设置 targets,例如:{"targets": {"chrome": "65", "firefox": "60", "safari": "11", "edge": "17"}} - 确保未手动添加
@babel/plugin-transform-regenerator;若已添加,请移除 - 验证:编译后搜索产物中是否还有
regeneratorRuntime或_typeof类辅助函数(注意区分typeof检测与 regenerator 标识)
若必须兼容旧环境,改用 external + CDN 方式加载 runtime
当无法放弃 IE11 等支持时,避免将 regenerator-runtime 打包进主 bundle,而是外链引入:
- 安装运行时:
npm install --save regenerator-runtime - 在入口文件顶部显式导入(确保早于所有 generator 使用):
import 'regenerator-runtime/runtime'; - 配置 webpack
externals(Vue CLI 项目写在vue.config.js的configureWebpack中):externals: { 'regenerator-runtime': 'regeneratorRuntime' } - 在 HTML 模板中通过 script 标签引入 CDN 版本:
<script src="https://unpkg.com/regenerator-runtime@0.14.1/runtime.js"></script> - 效果:runtime 从 JS bundle 中剥离,复用浏览器缓存,且不参与 Tree-shaking 冗余判断
配合 useBuiltIns: 'usage' 避免冗余 polyfill 注入
regenerator-runtime 常和其它 polyfill 一起被 @babel/preset-env 自动引入。若仅因 generator 启用整个 runtime,却未用到 Promise.allSettled、Array.from 等,会造成浪费:
- 将
useBuiltIns设为'usage',而非'entry',让 Babel 按实际调用注入 polyfill - 搭配
core-js@3,并确保只 import 所需模块,例如:import 'core-js/stable/array/from';而非import 'core-js/stable'; - 这样即使保留 regenerator,也不会额外塞入几十 KB 的未使用 polyfill 代码










