问题背景

在开发基于 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"],
    }),
  ],
});

配置项说明

  1. targets
    定义需要支持的浏览器版本范围:

    defaults:兼容所有浏览器厂商的最新稳定版本。

    not IE 11:排除 IE 11。

    chromeAndroid>=52:兼容 Chrome Android 52 及以上。

    iOS>=13.1:兼容 iOS Safari 13.1 及以上。

  2. 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。

验证测试

  1. 真机测试
    在小米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: "失败" },
]
  1. 浏览器兼容性检查
    使用 Can I Use 或 Babel 浏览器兼容性表 确认目标浏览器是否支持配置的 Polyfill。

总结

  1. 问题核心
    旧版浏览器对 ES2020+ 特性支持不足,需通过构建工具提供降级代码和 Polyfill。
  2. 解决方案要点
    精准配置浏览器范围:通过 targets 明确兼容范围,避免过度 Polyfill。

按需注入 Polyfill:结合 modernPolyfills 和 additionalLegacyPolyfills 按需覆盖未自动检测的 API。

构建策略分离:为现代和旧版浏览器生成两套代码,平衡性能和兼容性。

  1. 最佳实践
    测试覆盖:在真机和模拟器中测试所有目标浏览器。

监控构建体积:避免因 Polyfill 过多导致旧版代码体积膨胀。

动态加载 Polyfill:对极少数旧版用户,可考虑按需动态加载 Polyfill。

附录

参考文档

  • Vite 官方文档 - @vitejs/plugin-legacy
  • core-js Polyfill 列表
  • Babel 浏览器兼容性配置

lion
760 声望207 粉丝

一个脱离了高级趣味的人