核心思路是按需注入而非全量引入:通过browserslist精准定义目标浏览器,结合useBuiltIns: 'usage'自动引入所需polyfill;启用modern模式生成现代包(type="module")与传统包(nomodule),实现双版本智能分发。

核心思路是按需注入,而不是一股脑全塞进去。现代浏览器不需要 ES5 回退代码,硬加只会拖慢加载速度、增大包体积。
用 browserslist 精准定义目标环境
在项目根目录的 browserslist 文件(或 package.json 的 browserslist 字段)里明确声明你真正要支持的浏览器范围,例如:
- "> 0.5%, last 2 versions, not dead, not IE 11" —— 覆盖主流用户,主动排除已淘汰的 IE11
- "Chrome >= 87, Safari >= 14, Firefox >= 85" —— 按具体版本锁定,更可控
Babel 和 Vue CLI 都会依据这个配置自动推导哪些语法需要转译、哪些 API 需要 polyfill,避免为 Chrome 120 加 Promise 补丁这种无意义操作。
启用 modern 模式,让构建自动分发双版本
Vue CLI 项目运行 vue-cli-service build --modern,它会生成两套资源:
立即学习“前端免费学习笔记(深入)”;
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 现代包(
app.xxx.js):用<script type="module">加载,不带任何 polyfill,仅面向支持 ES modules 的浏览器 - 传统包(
app-legacy.xxx.js):含 Babel 转译 + 按需 polyfill,通过<script nomodule>加载,只给老浏览器
HTML 中的加载逻辑由 CLI 自动生成,无需手动判断 UA 或写兼容脚本。
谨慎使用 useBuiltIns: 'entry' 或 'usage'
在 babel.config.js 中配置 @babel/preset-env 时,优先选 useBuiltIns: 'usage':
-
'usage':只在代码中实际用了某个新 API(比如Array.from)时,才引入对应 polyfill -
'entry':在入口文件 import 一次,就按 browserslist 全量注入所有可能用到的 polyfill,容易冗余 - 如果用了
'entry',必须在 main.js 第一行 写import 'core-js/stable'; import 'regenerator-runtime/runtime';
避免手动 import 全量 polyfill 库
像 import '@babel/polyfill' 或 import 'core-js' 这类写法,本质是把整套垫片全打包进来,不管项目是否用得上。应改用:
-
import 'core-js/stable/array/from';—— 只补一个 API -
import 'core-js/stable/promise';—— 只补 Promise - 或者更推荐交给 Babel 自动处理,靠
useBuiltIns: 'usage'+ browserslist 控制
第三方依赖如果有兼容问题,优先用 transpileDependencies 在 vue.config.js 中单独开启转译,而不是全局加 polyfill。

















