跨平臺技術演進

薄荷前端發表於2019-04-01

前言

大家好,我是simbawu,關於這篇文章,有問題歡迎來這裡討論。

隨著移動網際網路的普及和快速發展,手機成了網際網路行業最大的流量分發入口。以及隨著5G的快速發展,未來越來越多的“端”也會如雨後春筍般快速興起。而“快”作為網際網路的生存之道,為了佔領市場,企業也會積極跟進,快速佈局。同一個應用,各個“端”獨立開發,不僅開發週期長,而且人員成本高。同時,作為技術人員,也不應該滿足於這種重複、低能的工作狀態。在這樣的形勢下,跨平臺的技術方案也受到越來越多人和企業的關注。接下來,我將從原理、優缺點等方面為大家分享《跨平臺技術演進》。

H5

說到跨平臺,沒人不知道H5。不管是在Mac、Windows、Linux、iOS、Android還是其他平臺,只要給一個瀏覽器,連“月球”上它都能跑。

瀏覽器架構

下面,我們來看看讓H5如此橫行霸道的瀏覽器的架構:

瀏覽器架構

  • User Interface 使用者介面:提供使用者與瀏覽器互動
  • Browser Engine 瀏覽器引擎:控制渲染引擎與JS直譯器
  • Rendering Engine 渲染引擎:負責頁面渲染
  • JavaScript Interpreter JS直譯器:執行JS程式碼,輸出結果給渲染引擎
  • Networking 網路工作組:處理網路請求
  • UI Backend UI後端:繪製視窗小部件
  • Data Storage 資料儲存:管理使用者資料

瀏覽器由以上7個部分組成,而“渲染引擎”是效能優化的重中之重,一起了解其中的渲染原理。

渲染引擎原理

不同的瀏覽器核心不同,渲染過程會不太一樣,但主要流程還是一致的。

WebKit 主流程

分為下面6步驟:

  1. HTML解析出DOM Tree
  2. CSS解析出CSSOM
  3. DOM Tree與CSSOM關聯生成Render Tree
  4. Layout 根據Render Tree計算每個節點的尺寸、位置
  5. Painting 根據計算好的資訊繪製整個頁面的畫素資訊
  6. Composite 將多個複合圖層傳送給GPU,GPU會將各層合成,然後顯示在螢幕上。

從以上6步,我們可以總結渲染優化的要點:

  • Layout在瀏覽器渲染過程中比較耗時,應儘可能避免重排的產生
  • 複合圖層佔用記憶體比重非常高,可採用減小複合圖層進行優化

以上就是瀏覽器端的內容。但H5作為跨平臺技術的載體,是如何與不同平臺的App進行互動的呢?這時候JSBridge就該出場了。

JSBridge原理

JSBridge,顧名思義,是JS和Native之間的橋樑,用來進行JS和Native之間的通訊。

JS

通訊分為以下兩個維度:

  • JavaScript 呼叫 Native,有兩種方式:

    1. 攔截URL Scheme:URL Scheme是一種類似於url的連結(boohee://goods/876898),當web前端傳送URL Scheme請求之後,Native 攔截到請求並根據URL Scheme進行相關操作。
    2. 注入API:通過 WebView 提供的介面,向 JavaScript 的 Context(window)中注入物件或者方法,讓 JavaScript 呼叫時,直接執行相應的 Native 程式碼邏輯,達到 JavaScript 呼叫 Native 的目的。
  • Native 呼叫 JavaScript: JavaScript暴露一個物件如JSBridge給window,讓Native能直接訪問。

那麼App內載入H5的過程是什麼樣的呢?

App開啟H5過程

跨平臺技術演進

開啟H5分為4個階段:

  1. 互動無反饋
  2. 開啟頁面 白屏
  3. 請求API,處於loading狀態
  4. 出現資料,正常展現

這四步,對應的過程如上圖所以,我們可以針對性的做效能優化。

優缺點分析

下面,我們進行H5的優缺點分析:

優點

  • 跨平臺:只要有瀏覽器,任何平臺都可以訪問
  • 開發成本低:生態成熟,學習成本低,除錯方便
  • 迭代速度快:無需稽核,及時響應,使用者可毫無感知使用最新版

缺點

  • 效能問題:在反應速度、流暢度、動畫方面遠不及原生
  • 功能問題:對攝像頭、陀螺儀、麥克風等硬體支援較差

雖然H5目前還存在不足,但隨著PWA、WebAssembly等技術的進步,相信H5在未來能夠得到越來也好的發展。

小程式

2018年是微信小程式飛速發展的一年,19年,各大廠商快速跟進,已經有了很大的影響力。下面,我們以微信小程式為例,分析小程式的技術架構。

跨平臺技術演進

小程式跟H5一樣,也是基於Webview實現。但它包含View檢視層、App Service邏輯層兩部分,分別獨立執行在各自的WebView執行緒中。

View

可以理解為h5的頁面,提供UI渲染。由WAWebview.js來提供底層的功能,具體如下:

  • 訊息通訊封裝為WeixinJSBridge
  • 日誌元件Reporter封裝
  • wx api(UI相關)
  • 小程式元件實現和註冊
  • VirtualDOM,Diff和Render UI實現
  • 頁面事件觸發

每個視窗都有一個獨立的WebView程式,因此微信限制不能開啟超過5個層級的頁面來保障使用者體驗。

App Service

提供邏輯處理、資料請求、介面呼叫。由WAService.js來提供底層的功能,具體如下:

  • 日誌元件Reporter封裝
  • wx api
  • App,Page,getApp,getCurrentPages等全域性方法
  • AMD模組規範的實現

執行環境:

  • iOS:JavaScriptCore
  • Andriod:X5核心,基於Mobile Chrome 53/57
  • DevTool:nwjs Chrome 核心

僅有一個WebView程式

View & App Service通訊

檢視層和邏輯層通過系統層的JSBridage進行通訊,邏輯層把資料變化通知到檢視層,觸發檢視層頁面更新,檢視層將觸發的事件通知到邏輯層進行業務處理。

優缺點分析

優點

  • 預載入WebView,準備新頁面渲染
  • View層和邏輯層分離,通過資料驅動,不直接操作DOM
  • 使用Virtual DOM,進行區域性更新
  • 元件化開發

缺點

  • 仍使用WebView渲染,並非原生渲染,體驗不佳
  • 不能執行在非微信環境內
  • 沒有window、document物件,不能使用基於瀏覽器的JS庫
  • 不能靈活操作 DOM,無法實現較為複雜的效果
  • 頁面大小、開啟頁面數量都受到限制

既然WebView效能不佳,那有沒有更好的方案呢?下面我們看看React Native。

React Native

跨平臺技術演進

RN的理念是在不同平臺上編寫基於React的程式碼,實現Learn once, write anywhere。

Virtual DOM在記憶體中,可以通過不同的渲染引擎生成不同平臺下的UI,JS和Native之間通過Bridge通訊

React Native 工作原理

跨平臺技術演進

在 React 框架中,JSX 原始碼通過 React 框架最終渲染到了瀏覽器的真實 DOM 中,而在 React Native 框架中,JSX 原始碼通過 React Native 框架編譯後,與Native原生的UI元件進行對映,用原生代替DOM元素來渲染,在UI渲染上非常接近Native App。

React Native 與Native平臺通訊

跨平臺技術演進

  • React Native用JavaScriptCore作為JS的解析引擎,在Android上,需要應用自己附帶JavaScriptCore,iOS上JavaScriptCore屬於系統的一部分,不需要應用附帶。
  • 用Bridge將JS和原生Native Code連線起來。Native和 JavaScript 兩端都儲存了一份配置表,裡面標記了所有Native暴露給 JavaScript 的模組和方法。互動通過傳遞 ModuleId、MethodId 和 Arguments 進行。

優缺點分析

優點

  • 垮平臺開發:相比原生的ios 和 android app各自維護一套業務邏輯大同小異的程式碼,React Native 只需要同一套javascript 程式碼就可以執行於ios 和 android 兩個平臺,在開發、測試和維護的成本上要低很多。
  • 快速編譯:相比Xcode中原生程式碼需要較長時間的編譯,React Native 採用熱載入的即時編譯方式,使得App UI的開發體驗得到改善,幾乎做到了和網頁開發一樣隨時更改,隨時可見的效果。
  • 快速釋出:React Native 可以通過 JSBundle 即時更新 App。相比原來冗長的稽核和上傳過程,釋出和測試新功能的效率大幅提高。
  • 渲染和佈局更高效:React Native擺脫了WebView的互動和效能問題,同時可以直接套用網頁開發中的css佈局機制。脫了 autolayout 和 frame 佈局中繁瑣的數學計算,更加直接簡便。

缺點

  • 動畫效能差:React Native 在動畫效率和效能的支援還存在一些問題,效能上不如原生Api。
  • 不能完全遮蔽原生平臺:就目前的React Native 官方文件中可以發現仍有部分元件和API都區分了Android 和 IOS 版本,即便是共享元件,也會有平臺獨享的函式。也就是說仍不能真正實現嚴格意義上的“一套程式碼,多平臺使用”。另外,因為仍對ios 和android的原生細節有所依賴,所以需要開發者若不瞭解原生平臺,可能會遇到一些坑。
  • 生態不完善:缺乏很多基本控制元件,第三方開源質量良莠不齊

展望未來

雖然RN還存在不足,但RN新版本已經做了如下改進,並且RN團隊也在積極準備大版本重構,能否成為開發者們所信賴的跨平臺方案,讓我們拭目以待。

  1. 改變執行緒模式。UI 更新不再同時需要在三個不同的執行緒上觸發執行,而是可以在任意執行緒上同步呼叫 JavaScript 進行優先更新,同時將低優先順序工作推出主執行緒,以便保持對 UI 的響應。
  2. 引入非同步渲染能力。允許多個渲染並簡化非同步資料處理。
  3. 簡化 JSBridge,讓它更快、更輕量。

既然React Native在渲染方面還擺脫不了原生,那有沒有一種方案是直接操控GPU,自制引擎渲染呢,我們終於迎來了Flutter!

Flutter

Flutter是Google開發的一套全新的跨平臺、開源UI框架,支援iOS、Android系統開發,並且是未來新作業系統Fuchsia的預設開發套件。渲染引擎依靠跨平臺的Skia圖形庫來實現,依賴系統的只有圖形繪製相關的介面,可以在最大程度上保證不同平臺、不同裝置的體驗一致性,邏輯處理使用支援AOT的Dart語言,執行效率也比JavaScript高得多。

Flutter架構原理

跨平臺技術演進

  • Framework:由Dart實現,包括Material Design風格的Widget,Cupertino(針對iOS)風格的Widgets,文字/圖片/按鈕等基礎Widgets,渲染,動畫,手勢等。此部分的核心程式碼是:flutter倉庫下的flutter package,以及sky_engine倉庫下的io,async,ui(dart:ui庫提供了Flutter框架和引擎之間的介面)等package。
  • Engine:由C++實現,主要包括:Skia,Dart和Text。
    • Skia是開源的二維圖形庫,提供了適用於多種軟硬體平臺的通用API。其已作為Google Chrome,Chrome OS,Android, Mozilla Firefox, Firefox OS等其他眾多產品的圖形引擎,支援平臺還包括Windows7+,macOS 10.10.5+,iOS8+,Android4.1+,Ubuntu14.04+等。Skia作為渲染/GPU後端,在Android和Fuchsia上使用FreeType渲染,在iOS上使用CoreGraphics來渲染字型。
    • Dart部分主要包括:Dart Runtime,Garbage Collection(GC),如果是Debug模式的話,還包括JIT(Just In Time)支援。Release和Profile模式下,是AOT(Ahead Of Time)編譯成了原生的arm程式碼,並不存在JIT部分。
    • Text即文字渲染,其渲染層次如下:衍生自minikin的libtxt庫(用於字型選擇,分隔行)。HartBuzz用於字形選擇和成型。
  • Embedder:是一個嵌入層,即把Flutter嵌入到各個平臺上去,這裡做的主要工作包括渲染Surface設定,執行緒設定,以及外掛等。從這裡可以看出,Flutter的平臺相關層很低,平臺(如iOS)只是提供一個畫布,剩餘的所有渲染相關的邏輯都在Flutter內部,這就使得它具有了很好的跨端一致性。

Dart優勢

很多人會好奇,為什麼Flutter要用Dart,而不是用JavaScript開發,這裡列下Dart的優勢

  • Dart 的效能更好。Dart在 JIT模式下,速度與 JavaScript基本持平。但是 Dart支援 AOT,當以 AOT模式執行時,JavaScript便遠遠追不上了。速度的提升對高幀率下的檢視資料計算很有幫助。
  • Native Binding。在 Android上,v8的 Native Binding可以很好地實現,但是 iOS上的 JavaScriptCore不可以,所以如果使用 JavaScript,Flutter 基礎框架的程式碼模式就很難統一了。而 Dart的 Native Binding可以很好地通過 Dart Lib實現。
  • Fuchsia OS。Fuchsia OS內建的應用瀏覽器就是使用 Dart語言作為 App的開發語言。

優缺點分析

優點

  • 效能強大:在兩個平臺上重寫了各自的UIKit,對接到平臺底層,減少UI層的多層轉換,UI效能可以比肩原生
  • 優秀的語言特性:參考上面Dart優勢分析
  • 路由設計優秀:Flutter的路由傳值非常方便,push一個路由,會返回一個Future物件(也就是Promise物件),使用await或者.then就可以在目標路由pop,回到當前頁面時收到返回值。

缺點

  • 優點即缺點,Dart 語言的生態小,精通成本比較高
  • UI控制元件API設計不佳
  • 與原生融合障礙很多,不利於漸進式升級

總結

移動網際網路的普及和快速發展,跨平臺技術風起雲湧,這也是技術發展過程中的必經之路,等浪潮退去,才知道誰在裸泳。我個人更看好H5或類H5方案,給它一個瀏覽器,連“月球”都能跑,這才是真正的跨平臺,其他都是浮雲。

廣而告之

本文釋出於薄荷前端週刊,歡迎Watch & Star ★,轉載請註明出處。

歡迎討論,點個贊再走吧 。◕‿◕。 ~

相關文章