博客 / 詳情

返回

🔬 一文搞懂前端兼容問題

如果你喜歡我的文章,希望點贊👍 收藏 📁 評論 💬 三連支持一下,謝謝你,這對我真的很重要!

對於大部分開發者來説,版本兼容是一件存在感很低的事情,因為它在絕大部分情況下都是一行配置,在一些前端工具鏈(例如 Babel、CoreJS,Autoprefixer 等工具)的幫助下適配到目標瀏覽器,只會在一些大的 break change 事件(例如 Vue3 必須在支持 Proxy 的現代瀏覽器下才能運行)下才會關注這件不起眼的事情。

但當你稍微研究一下的時候,才會發現這塊兒內容知識非常雜,因為版本兼容的相關知識沒有那麼多內在邏輯性,很多細碎的知識點散落在在各個商業公司的博弈和版本變更中。前段時間因工作需要對部分語言/瀏覽器特性重點關注了一下,以此文做一下記錄。

本文主要記錄了移動端的版本適配問題,未對桌面端做更多的研究,後面有可能補充相關內容。

1.iOS & Safari

iOS 和 Android 雖然都是一年更新一個大版本,但受益於生態的封閉性,iOS 的更新率極高,基本上最近的兩個版本就能覆蓋 95% 以上的人羣。

例如 Apple 官方統計,截止到 2022-05-31,Apple 四年內推出的新機型中,iOS 15 已經有 89% 的裝機率,iOS 14 也有 10% 的裝機率;而在所有歷史機型裏,iOS 15iOS 14 加起來也有 96% 的裝機率,隔壁 Android 都羨慕哭了:

為什麼如此關注 iOS 的版本號?因為 iOS 版本基本上和 Safari 版本一一對應的,例如 iOS 15.6 上安裝着 Safari 15.6iOS 14.5 上安裝着 Safari 14.1,具體的映射關係可見 MDN 的映射表,或者可以看 core-js: SafariToIOS,所以我們基本上只要比對 iOS 版本號即可。

另外一個問題是,有一定 C 端開發經驗的開發者可能還會關注 iOS 上運行的是 UIWebView 還是 WKWebView,在 2022 年這個時間點其實已經不需要關注了,因為 Apple Store 已經發過公告,2020 12 月之後已經禁止含 UIWebView 的 APP 上架了,所以 iOS 平台只有 WKWebView 這一個 WebView 了,而且它兼容性也不錯,最低支持到 iOS 8

2.Android & Chrome

説完 iOS 我們再談談 Android。因為兩個操作系統的發展策略不同,再加上國內各大廠商的魔改,Android 從一開始就深陷碎片化的深淵,有 Android 開發經歷的同學一定都深有感觸。

Android 系統本身碎片化,Android 系統自帶的瀏覽器更碎片化。在 Android 早期,Android 版本和 Chrome 瀏覽器版本是有綁定關係的,那這個早期是有多早?那就是 Android 4,2014 年發佈,綁定了 Chrome 早期幾個版本,因為數據不多,我這裏就直接列出來:

// https://github.com/zloirock/core-js/blob/master/packages/core-js-compat/src/mapping.mjs
ChromeToAndroid: [
  [9, '3.0'],
  [12, '4.0'],
  [30, '4.4'],
  [33, '4.4.3'],
]

事情的轉機出現在 Android 5,這個版本里 WebView 被移植為一個獨立的 APK,可以獨立更新,不再和 Android 系統深度綁定。

Google 的想法初衷是好的,藉助於 Google 商店,解耦更利於瀏覽器的版本迭代。但是在國內多廠商魔改和一些網絡問題上,極有可能發生這樣的事情:對於一台 Android 5 手機,理論上用户可以安裝 Chrome 36 - Chrome 95 任意一個版本

所以和 iOS 對比起來,Android 因為他的開放性帶來嚴重的碎片化問題:Android 版本多樣,Chrome 版本多樣,還有各種魔改內核,對於開發者來説適配起來真的苦不堪言。

3.Web Browser

瞭解完操作系統的版本歷史,我們再看看瀏覽器上最關鍵的 JavaScript 語法兼容度。

JavaScript

最近十年內,JS 這門語言的的最大變革就是 ES6(ES2015)的發佈了,帶來了非常多的新特性。下面我搞了一個表格,列出幾個大家常用的 JS 語法是從哪個版本開始支持的:

語法/API iOS Chrome
Class 9 49
=> 10 45
const 11 49
let 11 49
Proxy 10 49
generators 10 39
Promise 8 33
async await 11 55
import export 10.3 61
... ... ...

我們可以看到,這些語法的最低支持版本集中在 iOS 10iOS 11Chrome 49Chrome 61 這幾個版本上,我們把它們的版本發佈時間列出來:

事件 發佈時間
ES5 標準發佈時間 2009.12
ES6 標準發佈時間 2015.06
iOS 10 發佈時間 2016.06
iOS 11 發佈時間 2017.06
Chrome 49 發佈時間 2016.03
Chrome 61 發佈時間 2017.09

時間列出來後結論基本上是呼之欲出了:ES6 標準發佈後的未來一年時間內,各大瀏覽器語法就支持的差不多了,兩年後基本上就全部支持了這個時間點就是 2017 年,對應着 iOS 11 Chrome 61

legacy vs modern

看完 ES6 的支持情況,我們再來了解兩個概念,「經典瀏覽器」和「現代瀏覽器」。

這兩個詞在英文裏對應着「legacy browser」和「modern browser」。如果大家比較關注一些相對前沿的前端項目,比如説 Vue3,Solidjs,Vite,它們的官網裏其實經常提到這兩個詞。

那麼問題來了,既然有兩個稱呼,那在工程裏必然存在一個分界線去區分 legacy 和 modern,這個分界線就是 iOS10.3Chrome 61,既瀏覽器支持 ES Modules 的版本(支持 <script type="module"> & import & export)。

這樣一看是不是就和上面的內容對上了?Babel 官網也做了相關的解釋,core-js 也專門做了區分,更詳細的介紹可以看 MDN 的文章:JavaScript modules,我就不做多餘介紹了。

modern feature

經過上面的探索,我們再回過來看看一些比較 modern 的 browser feature 的支持程度:

browser fature iOS Chrome
Web Worker 5 4
SubtleCrypto 7 37
Service Worker 11.3 45
WebAssembly 11 57
CSS Grid Layout 10.3 58
WebGPU not support not support
... ... ...

看看各個 API 的兼容度,再結合上文的內容,就可以發現很多「兼容性不好」人云亦云的説法不攻自破,其實大部分情況下不是兼容度不好從而不用,是項目還沒有複雜到那個程度需要用這些高級功能

4.Open Source Project

日常開發中肯定不能寫一行代碼查一下兼容度,這些都是由社區工具做抹平的。

兼容度數據源頭可以追述到 MDN 的 browser-compat-data,記錄了各種 API 的兼容,MDN 網站的兼容度直接是從這個 repo 裏讀的。我們常用的 caniuse 網站,一部分數據也是依賴於它的。

接下來是工程上依賴最多的 browserslist,babel、eslint、autoprefixer、postcss,webpack 等構建工具都依賴於它,browserslist 的數據又依賴於 caniuse-lite,其實也是依賴於 caniuse,lite 只保留了核心數據,對一些説明文案做了裁剪處理。

綜合以上分析,我們可以看出,在項目工程裏依賴的 browserslist,數據準確性還是可以得到保證的,所以兼容性還是無需擔心的。

5.Adaptation Suggestions

説了這麼多,那麼有什麼配置建議呢?我個人認為主要有 3 點建議提供參考。

第一個是參考國民級 APP 的最低支持度配置

在國內,在日活上能稱為國民級 APP 的就是微信抖音了,這兩個 APP 因為日活巨大,基本上已經覆蓋到全部中國人,所以他們的配置一定有所考量,可以反應出國內的整體手機版本水平。

從 App Store/Android 應用商店/瀏覽器 UA 上看,我們可以得處以下結論(截止到 2022-8-8):

  • 微信:最低支持到 iOS 12Android 5、內置瀏覽器版本為 Chrome 86
  • 抖音:最低支持到 iOS 10Android 5、內置瀏覽器版本為 Chrome 75

當然你也可以參考其他 APP,由於精力有限我就不做過多展開了。

根據項目的迭代速度來看,iOS 基本上可以做到一年一升級,比如説今年 iOS 16 出來後,明年最低適配版本基本上可以升到 iOS 11 了,Android 因為長尾效應和版本不綁定的問題,應該還會支持到 Android 5

第二個建議是直接看當前業務的版本數據

不同的公司不同的項目都有不同的用户場景,比如説面向三四線 C 端用户的場景,一般低端機就會多一些;面向門店的場景,説不定還得適配 IE 瀏覽器;面向企業內的開發者項目,直接適配到最新幾個瀏覽器即可。

場景如此之多就要依賴於用户版本數據統計了。一般中大廠都有比較完善的數據監控中台,直接拉一份數據就能獲取大致情況,基建不完善的小公司也可以單獨開個接口記錄數據,收集一個月做個去重統計也能得到相關數據。拿到數據後再結合業務場景做些取捨,基本上就可以拿到最低適配了。

第三個建議結合前端框架和 Chrome 版本做兼容。

結合前端框架其實很好理解,比如説你用了 Vue3,底層依賴於 Proxy,那麼最低依賴已經鎖死到 iOS 10Chrome 49 了,那你的最低配置只能比以上版本高,假如你無腦設置為 iOS 9Android 4,除了在最低版本上跑不起來,還要平白無故的多了許多語法轉換和 polyfill,在 構建速度/運行時性能/產物體積 上都會產生不必要的劣化。

結合 Chrome 版本做兼容其實就是本文第二大節的內容。因為 Android 5 之後不再和 Chrome 做深度綁定,版本兼容設置 Android 版本其實是無意義的行為,應該根據統計結果直接設置 Chrome 版本,做更細粒度的配置。

Refs: Version History

以上的版本歷史和發佈時間主要參考官方更新日誌/文檔 和 維基百科,相關鏈接如下所示:

  • iOS 版本歷史:https://en.wikipedia.org/wiki/IOS_version_history
  • Android 版本歷史:https://en.wikipedia.org/wiki/Android_version_history
  • Chrome 版本歷史:https://en.wikipedia.org/wiki/Google_Chrome_version_history
  • WKWebView API 兼容度:https://developer.apple.com/documentation/webkit/wkwebview
  • Android Verison 和 APILevel 的對應關係:https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels





如果你喜歡我的文章,希望點贊👍 收藏 📁 評論 💬 三連支持一下,謝謝你,這對我真的很重要!

歡迎大家關注我的微信公眾號:滷蛋實驗室,目前專注前端技術,對圖形學也有一些微小研究。

原文鏈接 👉 🔬 對前端版本兼容問題的研究:更新更及時,閲讀體驗更佳。

user avatar laughingzhu 頭像 xiangjiaochihuanggua 頭像 yaofly 頭像 esunr 頭像 coderleo 頭像 _raymond 頭像 ailim 頭像 liyl1993 頭像 fehaha 頭像 wupengyu_55d86cdb45293 頭像 yihan123 頭像 thehumble 頭像
20 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.