问题背景
在开发基于 Vite 的 Web 应用时,使用 Promise.allSettled
方法时发现,在部分旧版安卓设备(如小米8,Android 8.1.0)上运行时,控制台报错 TypeError: Promise.allSettled is not a function
。该问题导致应用功能异常,影响用户体验。
受影响的设备环境
- 设备:小米8(Android 8.1.0)
- 浏览器/WebView:Chrome 60~68(Android 8.1.0 默认浏览器内核)
- 问题现象:
Promise.allSettled
未定义,代码执行中断。
问题原因分析
1. 浏览器兼容性不足
Android 8.1.0 默认浏览器或 WebView 基于 Chrome 60 左右,而 Promise.allSettled
是 ES2020(ES11)引入的特性,支持环境为:
- Chrome ≥76
- Firefox ≥71
- Safari ≥13.1
- Edge ≥79
旧版浏览器未实现该 API,导致代码报错。
2. Vite 默认构建策略
Vite 默认以现代浏览器为构建目标(如支持 ES 模块的浏览器),生成的代码可能包含未降级的 ES2020+ 语法,旧版浏览器无法解析。
3. 未正确注入 Polyfill
项目中未对旧版浏览器提供 Promise.allSettled
的 Polyfill 支持,导致目标环境无法识别该 API。
解决方案
通过 @vitejs/plugin-legacy
插件配置,针对旧版浏览器生成兼容代码并注入必要的 Polyfill。
步骤 1:安装依赖
npm install @vitejs/plugin-legacy --save-dev
步骤 2:配置 vite.config.ts
import { defineConfig } from "vite";
import legacy from "@vitejs/plugin-legacy";
export default defineConfig({
plugins: [
legacy({
// 指定目标浏览器范围
targets: ["defaults", "not IE 11", "chromeAndroid>=52", "iOS>=13.1"],
// 为现代浏览器添加必要的 Polyfill(此处需结合业务场景)
modernPolyfills: ["es/promise", "es/array"],
}),
],
});
配置项说明
targets
定义需要支持的浏览器版本范围:defaults:兼容所有浏览器厂商的最新稳定版本。
not IE 11:排除 IE 11。
chromeAndroid>=52:兼容 Chrome Android 52 及以上。
iOS>=13.1:兼容 iOS Safari 13.1 及以上。
modernPolyfills
为现代浏览器手动添加 Polyfill(需结合代码中使用的特性)。例如:es/promise:提供 Promise 相关 Polyfill。
es/array:提供 Array 相关方法(如 Array.prototype.includes)。
步骤 3:验证 Polyfill 注入
构建项目后,检查生成的 HTML 文件是否包含旧版代码块:
<script nomodule src="/assets/legacy.js"></script>
<script type="module" src="/assets/modern.js"></script>
旧版浏览器(如 Android 8.1.0)会加载 legacy.js,其中包含降级代码和 Polyfill。
验证测试
真机测试
在小米8(Android 8.1.0)设备中:清除浏览器缓存。
打开应用,检查控制台是否报错。
执行以下代码验证 Promise.allSettled:
const promises = [
Promise.resolve("成功"),
Promise.reject("失败"),
];
Promise.allSettled(promises).then((results) => {
console.log(results);
});
预期输出:
[
{ status: "fulfilled", value: "成功" },
{ status: "rejected", reason: "失败" },
]
- 浏览器兼容性检查
使用 Can I Use 或 Babel 浏览器兼容性表 确认目标浏览器是否支持配置的 Polyfill。
总结
- 问题核心
旧版浏览器对 ES2020+ 特性支持不足,需通过构建工具提供降级代码和 Polyfill。 - 解决方案要点
精准配置浏览器范围:通过 targets 明确兼容范围,避免过度 Polyfill。
按需注入 Polyfill:结合 modernPolyfills 和 additionalLegacyPolyfills 按需覆盖未自动检测的 API。
构建策略分离:为现代和旧版浏览器生成两套代码,平衡性能和兼容性。
- 最佳实践
测试覆盖:在真机和模拟器中测试所有目标浏览器。
监控构建体积:避免因 Polyfill 过多导致旧版代码体积膨胀。
动态加载 Polyfill:对极少数旧版用户,可考虑按需动态加载 Polyfill。
附录
参考文档
- Vite 官方文档 - @vitejs/plugin-legacy
- core-js Polyfill 列表
- Babel 浏览器兼容性配置
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。