👆👆關注我👆👆
對於大部分開發者來說,版本兼容是一件存在感很低的事情,因為它在絕大部分情況下都是一行配置,在一些前端工具鏈(例如 Babel、CoreJS,Autoprefixer 等工具)的幫助下適配到目標瀏覽器,只會在一些大的 break change 事件(例如 Vue3 必須在支持 Proxy 的現代瀏覽器下才能運行)下才會關注這件不起眼的事情。
但當你稍微研究一下的時候,才會發現這塊兒內容知識非常雜,因為版本兼容的相關知識沒有那麼多內在邏輯性,很多細碎的知識點散落在在各個商業公司的博弈和版本變更中。前段時間因工作需要對部分語言/瀏覽器特性重點關注了一下,以此文做一下記錄。
本文主要記錄了移動端的版本適配問題,未對桌面端做更多的研究,後面有可能補充相關內容。
1.iOS & SafariiOS 和 Android 雖然都是一年更新一個大版本,但受益於生態的封閉性,iOS 的更新率極高,基本上最近的兩個版本就能覆蓋 95% 以上的人群。
例如 Apple 官方統計[1],截止到 2022-05-31,Apple 四年內推出的新機型中,iOS 15 已經有 89% 的裝機率,iOS 14 也有 10% 的裝機率;而在所有歷史機型里,iOS 15 和 iOS 14 加起來也有 96% 的裝機率,隔壁 Android 都羨慕哭了:
為什麼如此關注 iOS 的版本號?因為 iOS 版本基本上和 Safari 版本一一對應的,例如 iOS 15.6 上安裝着 Safari 15.6,iOS 14.5 上安裝着 Safari 14.1,具體的映射關係可見 MDN 的映射表[2],或者可以看 core-js: SafariToIOS[3],所以我們基本上只要比對 iOS 版本號即可。
另外一個問題是,有一定 C 端開發經驗的開發者可能還會關注 iOS 上運行的是 UIWebView 還是 WKWebView,在 2022 年這個時間點其實已經不需要關注了,因為 Apple Store 已經發過公告[4],2020 12 月之後已經禁止含 UIWebView 的 APP 上架了,所以 iOS 平台只有 WKWebView 這一個 WebView 了,而且它兼容性也不錯[5],最低支持到 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.mjsChromeToAndroid:[[9,'3.0'],[12,'4.0'],[30,'4.4'],[33,'4.4.3'],]事情的轉機出現在 Android 5,這個版本[6]里 WebView 被移植為一個獨立的 APK,可以獨立更新,不再和 Android 系統深度綁定。
Google 的想法初衷是好的,藉助於 Google 商店,解耦更利於瀏覽器的版本迭代。但是在國內多廠商魔改和一些網絡問題上,極有可能發生這樣的事情:對於一台 Android 5 手機,理論上用戶可以安裝 Chrome 36 - Chrome 95 任意一個版本!
所以和 iOS 對比起來,Android 因為他的開放性帶來嚴重的碎片化問題:Android 版本多樣,Chrome 版本多樣,還有各種魔改內核,對於開發者來說適配起來真的苦不堪言。
3.Web Browser了解完操作系統的版本歷史,我們再看看瀏覽器上最關鍵的 JavaScript 語法兼容度。
JavaScript最近十年內,JS 這門語言的的最大變革就是 ES6(ES2015)的發布了,帶來了非常多的新特性。下面我搞了一個表格,列出幾個大家常用的 JS 語法是從哪個版本開始支持的:
我們可以看到,這些語法的最低支持版本集中在 iOS 10、iOS 11,Chrome 49,Chrome 61 這幾個版本上,我們把它們的版本發布時間列出來:
時間列出來後結論基本上是呼之欲出了:ES6 標準發布後的未來一年時間內,各大瀏覽器語法就支持的差不多了,兩年後基本上就全部支持了,這個時間點就是 2017 年,對應着 iOS 11 和 Chrome 61。
legacy vs modern看完 ES6 的支持情況,我們再來了解兩個概念,「經典瀏覽器」和「現代瀏覽器」。
這兩個詞在英文裡對應着「legacy browser」和「modern browser」。如果大家比較關注一些相對前沿的前端項目,比如說 Vue3,Solidjs,Vite,它們的官網裡其實經常提到這兩個詞。
那麼問題來了,既然有兩個稱呼,那在工程里必然存在一個分界線去區分 legacy 和 modern,這個分界線就是 iOS10.3 和 Chrome 61,既瀏覽器支持 ES Modules 的版本(支持 <script type="module"> & import & export)。
這樣一看是不是就和上面的內容對上了?Babel 官網也做了相關的解釋[7],core-js 也專門做了區分[8],更詳細的介紹可以看 MDN 的文章:JavaScript modules[9],我就不做多餘介紹了。
modern feature經過上面的探索,我們再回過來看看一些比較 modern 的 browser feature 的支持程度:
看看各個 API 的兼容度,再結合上文的內容,就可以發現很多「兼容性不好」人云亦云的說法不攻自破,其實大部分情況下不是兼容度不好從而不用,是項目還沒有複雜到那個程度需要用這些高級功能。
4.Open Source Project日常開發中肯定不能寫一行代碼查一下兼容度,這些都是由社區工具做抹平的。
兼容度數據源頭可以追述到 MDN 的 browser-compat-data[10],記錄了各種 API 的兼容,MDN 網站的兼容度直接是從這個 repo 里讀的。我們常用的 caniuse[11] 網站,一部分數據也是依賴於它的。
接下來是工程上依賴最多的 browserslist[12],babel、eslint、autoprefixer、postcss,webpack 等構建工具都依賴於它,browserslist 的數據又依賴於 caniuse-lite[13],其實也是依賴於 caniuse[14],lite 只保留了核心數據,對一些說明文案做了裁剪處理。
綜合以上分析,我們可以看出,在項目工程里依賴的 browserslist,數據準確性還是可以得到保證的,所以兼容性還是無需擔心的。
5.Adaptation Suggestions說了這麼多,那麼有什麼配置建議呢?我個人認為主要有 3 點建議提供參考。
第一個是參考國民級 APP 的最低支持度配置。
在國內,在日活上能稱為國民級 APP 的就是微信抖音了,這兩個 APP 因為日活巨大,基本上已經覆蓋到全部中國人,所以他們的配置一定有所考量,可以反應出國內的整體手機版本水平。
從 App Store/Android 應用商店/瀏覽器 UA 上看,我們可以得處以下結論(截止到 2022-8-8):
當然你也可以參考其他 APP,由於精力有限我就不做過多展開了。
根據項目的迭代速度來看,iOS 基本上可以做到一年一升級,比如說今年 iOS 16 出來後,明年最低適配版本基本上可以升到 iOS 11 了,Android 因為長尾效應和版本不綁定的問題,應該還會支持到 Android 5。
第二個建議是直接看當前業務的版本數據。
不同的公司不同的項目都有不同的用戶場景,比如說面向三四線 C 端用戶的場景,一般低端機就會多一些;面向門店的場景,說不定還得適配 IE 瀏覽器;面向企業內的開發者項目,直接適配到最新幾個瀏覽器即可。
場景如此之多就要依賴於用戶版本數據統計了。一般中大廠都有比較完善的數據監控中台,直接拉一份數據就能獲取大致情況,基建不完善的小公司也可以單獨開個接口記錄數據,收集一個月做個去重統計也能得到相關數據。拿到數據後再結合業務場景做些取捨,基本上就可以拿到最低適配了。
第三個建議結合前端框架和 Chrome 版本做兼容。
結合前端框架其實很好理解,比如說你用了 Vue3,底層依賴於 Proxy,那麼最低依賴已經鎖死到 iOS 10 和 Chrome 49 了,那你的最低配置只能比以上版本高,假如你無腦設置為 iOS 9 或 Android 4,除了在最低版本上跑不起來,還要平白無故的多了許多語法轉換和 polyfill,在 構建速度/運行時性能/產物體積 上都會產生不必要的劣化。
結合 Chrome 版本做兼容其實就是本文第二大節的內容。因為 Android 5 之後不再和 Chrome 做深度綁定,版本兼容設置 Android 版本其實是無意義的行為,應該根據統計結果直接設置 Chrome 版本,做更細粒度的配置。
Refs: Version History以上的版本歷史和發布時間主要參考官方更新日誌/文檔 和 維基百科,相關鏈接如下所示:
Apple 官方統計: https://developer.apple.com/support/app-store/
[2]MDN 的映射表: https://github.com/mdn/browser-compat-data/blob/main/browsers/safari_ios.json
[3]core-js: SafariToIOS: https://github.com/zloirock/core-js/blob/master/packages/core-js-compat/src/mapping.mjs
[4]公告: https://developer.apple.com/cn/news/?id=edwud51q
[5]兼容性也不錯: https://developer.apple.com/documentation/webkit/wkwebview
[6]這個版本: https://developer.chrome.com/docs/multidevice/webview/
[7]解釋: https://babeljs.io/docs/en/options#targetsesmodules
[8]區分: https://github.com/zloirock/core-js/blob/master/packages/core-js-compat/src/external.mjs
[9]JavaScript modules: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
[10]browser-compat-data: https://github.com/mdn/browser-compat-data
[11]caniuse: https://caniuse.com/
[12]browserslist: https://github.com/browserslist/browserslist
[13]caniuse-lite: https://github.com/browserslist/caniuse-lite
[14]caniuse: https://github.com/Fyrd/caniuse
往期推薦
Copilot 突然收費!免費的 AI 幫忙寫代碼突然不香了?
僅用一個HTML標籤,實現帶動畫的抖音Logo
我最期待的 3 個即將推出的 CSS 特性!
CSS 穿牆術!太強了
CSS 中的簡寫到底有多少坑?以後不敢了...
小程序前景無限,還能一鍵轉換成App?
創作不易,加個點讚、在看支持一下哦!