React项目替换babel-runtime为polyfill.io遇包体积增大及方案咨询
transform-runtime后打包体积反而变大了? 你碰到的这个问题,核心是对babel-plugin-transform-runtime的作用理解有偏差——它不止负责处理polyfill,更关键的功能是复用Babel编译过程中生成的辅助函数(像_classCallCheck、_extends这类每次编译类、扩展对象都会用到的工具函数)。
之前有这个插件的时候,这些辅助函数都是从babel-runtime包里统一引入的,整个项目里只会存在一份。但你把插件移除后,Babel就会把这些函数直接内嵌到每一个用到它们的文件里——如果你的项目有几十个组件都用到这些函数,重复的代码堆起来,体积自然就涨了29KB。你本来以为移除polyfill会让体积变小,但忽略了这个插件的辅助函数复用功能,才出现了反效果。
要顺利完成切换,得同时搞定“不让Babel打包polyfill”和“保留辅助函数复用”这两件事,具体操作如下:
1. 调整Babel配置,精准控制polyfill和辅助函数
修改你的webpack里的babel配置,既要禁用Babel打包polyfill,又要保留辅助函数的复用(避免体积膨胀):
module: { rules: [ { test: /.jsx?$/, loader: 'babel-loader', include: [path.resolve(__dirname, "src")], query: { presets: [ ['env', { useBuiltIns: false, // 明确告诉Babel:别把polyfill打包进来 targets: { // 这里保留你的目标浏览器配置,比如支持最近2个版本、IE10+ browsers: ['last 2 versions', 'ie >= 10'] } }], 'react', 'stage-0' ], // 重新加上transform-runtime,但只启用辅助函数复用功能 plugins: [ ['transform-runtime', { polyfill: false, // 关键:禁止从babel-runtime引入polyfill regenerator: true // 如果你的项目用了async/await,就保留这个,否则可以设为false }] ] } }, ] }
2. 在HTML里引入polyfill.io的按需加载脚本
把polyfill.io的脚本加到项目入口HTML的<head>里,它会自动识别用户的浏览器,只加载该浏览器缺失的polyfill,完全不用你操心兼容细节:
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6,es7,Intl"></script>
你可以通过features参数自定义需要的特性,比如只需要ES6核心能力就写features=es6,按需调整就行。
3. 清理冗余依赖(可选)
如果你之前装了babel-runtime,现在因为禁用了polyfill部分,你可以看看项目是否还需要完整的包——不过因为还要复用辅助函数,所以这个依赖还是得留着;要是你的项目没用到async/await,把regenerator设为false还能再减点体积。
4. 验证打包结果
改完配置重新打包后,你会发现:
- 打包后的代码不再包含全局polyfill,体积会比之前带polyfill的版本小很多
- 辅助函数依然是从
babel-runtime统一引入,不会出现之前的重复内嵌代码,体积也就不会莫名上涨了
内容的提问来源于stack exchange,提问作者DFB




