博客 / 詳情

返回

解決 Vite 項目中 Android 8.1.0 設備 Promise.allSettled 失效問題

問題背景

在開發基於 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 瀏覽器兼容性配置
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.