Polyfill 的含义
基本定义
Polyfill(填充物)是一段代码,用于在旧浏览器中实现新浏览器才有的功能。它让旧浏览器也能使用新的 JavaScript API 或语法特性。
名称来源
- Poly = 多种/多个
- Fill = 填充
意思是"用代码填充缺失的功能"。
工作原理
当浏览器不支持某个 API 时,polyfill 会:
- 检测浏览器是否支持该功能
- 如果不支持,用旧 API 或兼容方式实现相同功能
- 让代码在旧浏览器中也能正常运行
vite 项目配置
1. package.json 配置 browserslist
因为我开发的,是 h5 的 C 端项目,所以配置如下,具体的兼容浏览器列表要根据实际情况定
json
"browserslist": [
"> 0.5%",
"last 2 versions",
"iOS >= 10",
"Android >= 5",
"not dead",
"not ie 11",
"not op_mini all"
]
配置项说明:
- "> 0.5%"(市场占有率):支持全球市场份额 > 0.5% 的浏览器,覆盖主流浏览器
- "last 2 versions"(最新版本):支持每个浏览器的最新 2 个版本,例如:Chrome 最新版和上一个版本
- "iOS >= 10"(iOS Safari):支持 iOS 10 及以上的 Safari,覆盖 iPhone/iPad 的常见版本
- "Android >= 5"(Android):支持 Android 5.0(Lollipop)及以上,覆盖大部分 Android 设备
- "not dead"(排除已停止维护):排除已停止维护的浏览器,例如:IE 10 及以下、旧版 Opera
- "not ie 11"(排除 IE 11):明确排除 IE 11
- "not op_mini all"(排除 Opera Mini):排除所有版本的 Opera Mini,Opera Mini 功能受限,通常不支持现代特性
2. 安装依赖
@vitejs/plugin-legacy:兼容 Vite 5
terser:用于压缩 legacy 构建产物
perl
npm install --save-dev "@vitejs/plugin-legacy@^5.4.0" terser
3. 配置 Vite
在 vite.config.js 中,插件会自动读取 package.json 中的 browserslist 配置
javascript
import legacy from '@vitejs/plugin-legacy';
export default defineConfig(({ mode }) => ({
plugins: [
vue(),
createHtmlPlugin({ inject: { data: { ...conf } } }),
legacy({
// 自动读取 package.json 中的 browserslist 配置
modernPolyfills: true,
renderLegacyChunks: true
})
],
// ......
}
babel.config.js无需调整,因为 @vitejs/plugin-legacy 会自动处理 polyfill。
browserslist 与 Legacy 代码的关系
工作原理
browserslist 定义的是"目标浏览器范围"(需要支持的浏览器)。@vitejs/plugin-legacy 的工作流程:
构建时:
- 根据 browserslist 生成两套代码:
- 现代版本(modern):ES6+ 语法,给新浏览器
- Legacy 版本(legacy):转译后的 ES5 代码 + polyfill,给旧浏览器
运行时(浏览器访问时):
- 通过特性检测(feature detection)判断浏览器能力
- 支持现代特性的浏览器 → 加载现代版本
- 不支持现代特性的浏览器 → 加载 Legacy 版本
运行时检测机制:
@vitejs/plugin-legacy 会在 HTML 中注入类似这样的代码:
xml
<script type="module" src="modern.js"></script>
<script nomodule src="legacy.js"></script>
- 支持 ES modules 的浏览器 → 加载 modern.js
- 不支持 ES modules 的浏览器 → 加载 legacy.js(包含 polyfill)
举例说明
假设配置是:
json
"browserslist": [
"> 0.5%",
"iOS >= 10",
"Android >= 5"
]
不同浏览器的处理:
| 浏览器类型 | 是否在 browserslist 内 | 实际加载的代码 |
|---|---|---|
| iOS Safari 12(新) | ✅ 在范围内 | 现代版本(modern) |
| iOS Safari 10(旧) | ✅ 在范围内 | Legacy 版本(legacy + polyfill) |
| iOS Safari 9(更旧) | ❌ 不在范围内 | Legacy 版本(可能不完整,可能报错) |
| Chrome 120(最新) | ✅ 在范围内 | 现代版本(modern) |
| Chrome 50(旧) | ✅ 在范围内 | Legacy 版本(legacy + polyfill) |
| IE 11 | ❌ 被排除 | 不加载(配置了 not ie 11) |
总结
- browserslist 是"最低支持标准"
- 在范围内的旧浏览器 → 会加载 legacy 代码
- 在范围内的新浏览器 → 会加载现代代码(性能更好)
- 不在范围内的更旧浏览器 → 可能加载 legacy,但不保证完全兼容
- 被明确排除的浏览器(如 not ie 11)→ 不生成支持代码