根據(jù)實現(xiàn)方式的不同,業(yè)內常見的觀點是將主流的跨平臺方案劃分為三個時代娘侍。
Web 容器時代:基于 Web 相關技術通過瀏覽器組件來實現(xiàn)界面及功能咖刃,典型的框架包括 Cordova(PhoneGap)、Ionic 和微信小程序憾筏。
泛 Web 容器時代:采用類 Web 標準進行開發(fā)僵缺,但在運行時把繪制和渲染交由原生系統(tǒng)接管的技術,代表框架有 React Native踩叭、Weex 和快應用磕潮,廣義的還包括天貓的 Virtual View 等翠胰。
自繪引擎時代:自帶渲染引擎,客戶端僅提供一塊畫布即可獲得從業(yè)務邏輯到功能呈現(xiàn)的多端高度一致的渲染體驗自脯。Flutter之景,是為數(shù)不多的代表。
Web 容器時代
Web 時代的方案膏潮,主要采用的是原生應用內嵌瀏覽器控件 WebView(iOS 為 UIWebView 或 WKWebView锻狗,Android 為 WebView)的方式進行 HTML5 頁面渲染,并定義 HTML5 與原生代碼交互協(xié)議焕参,將部分原生系統(tǒng)能力暴露給 HTML5轻纪,從而擴展 HTML5 的邊界。這類交互協(xié)議叠纷,就是我們通常說的 JS Bridge(橋)库倘。
一個完整 HTML5 頁面的展示要經歷瀏覽器控件的加載济舆、解析和渲染三大過程巷屿,性能消耗要比原生開發(fā)增加 N 個數(shù)量級省核。接下來,我以加載過程為例航厚,和你說明這個過程的復雜性顷歌。
瀏覽器控件加載 HTML5 頁面的 HTML 主文檔;
加載過程中遇到外部 CSS 文件幔睬,瀏覽器另外發(fā)出一個請求眯漩,來獲取 CSS 文件;
遇到圖片資源麻顶,瀏覽器也會另外發(fā)出一個請求赦抖,來獲取圖片資源。這是異步請求澈蚌,并不會影響 HTML 文檔的加載摹芙。
加載過程中遇到 JavaScript 文件,由于 JavaScript 代碼可能會修改 DOM 樹宛瞄,因此 HTML 文檔會掛起渲染(加載解析渲染同步)的線程浮禾,直到 JavaScript 文件加載解析并執(zhí)行完畢,才可以恢復 HTML 文檔的渲染線程份汗。
JavaScript 代碼中有用到 CSS 文件中的屬性樣式盈电,于是阻塞,等待 CSS 加載完畢才能恢復執(zhí)行杯活。
瀏覽器保證了 99% 的概率下 Web 的需求都是可以實現(xiàn)的匆帚,不需要業(yè)務將就“技術”。不過旁钧,Web 最大的問題在于它的性能和體驗與原生開發(fā)存在肉眼可感知的差異吸重,因此并不適用于對體驗要求較高的場景互拾。
泛 Web 容器時代
基本上完全放棄了瀏覽器控件渲染,而是采用原生自帶的 UI 組件實現(xiàn)代替了核心的渲染引擎嚎幸。 仍然采用前端友好的 JavaScript 進行開發(fā)颜矿,整體加載、渲染機制大大簡化嫉晶,并且由原生接管繪制骑疆,即將原生系統(tǒng)作為渲染的后端,為依托于 JavaScript 虛擬機的 JavaScript 代碼提供所需要的 UI 控件的實體替废。如RN箍铭。
對于用戶體驗更接近于原生的 React Native,對業(yè)務的支持能力卻還不到瀏覽器的 5%椎镣,僅適用于中低復雜度的低交互類頁面诈火。面對稍微復雜一點兒的交互和動畫需求,開發(fā)者都需要 case by case 地去 review衣陶,甚至還可能要通過原生代碼去擴展才能實現(xiàn)柄瑰。
自繪引擎時代
泛 Web 容器時代使用原生控件承載界面渲染闸氮,固然解決了不少性能問題剪况,但同時也帶來了新的問題。拋開框架本身需要處理大量平臺相關的邏輯外蒲跨,隨著系統(tǒng)版本變化和 API 的變化译断,我們還需要處理不同平臺的原生控件渲染能力差異,修復各類奇奇怪怪的 Bug或悲。始終需要 Follow Native 的思維方式孙咪,就使得泛 Web 容器框架的跨平臺特性被大打折扣。