移動跨平臺技術方案總結

xiangzhihong發表於2019-01-22

“得移動端者得天下”,移動端取代PC端,成為了網際網路行業最大的流量分發入口,因此不少公司制定了“移動優先”的發展策略。

為了幫助讀者更好地學習WEEX,本節將對React Native、Weex和Flutter等主流的跨平臺方案進行簡單的介紹和對比。

React Native

React Native (簡稱RN)是Facebook於2015年4月開源的跨平臺移動應用開發框架,是Facebook早先開源的React框架在原生移動應用平臺的衍生產物,目前主要支援iOS和安卓兩大平臺。

RN使用Javascript語言來開發移動應用,但UI渲染、網路請求等均由原生端實現。具體來說,開發者編寫的Javascript程式碼,通過中間層轉化為原生控制元件後再執行,因此熟悉Web前端開發的技術人員只需很少的學習就可以進入移動應用開發領域,並可以在不犧牲使用者體驗的前提下提高開發效率。

作為一個跨平臺技術框架,RN從上到下可以分為Javascript層、C++層和Native層。其中,C++層主要用於實現動態連結庫(.so),作為中間適配層橋接,實現js端與原生端的雙向通訊互動,如下圖所示是RN在Android平臺上的通訊原理圖。

在這裡插入圖片描述

在RN的三層架構中,最核心的就是中間的C++層,C++層最核心的功能就是封裝JavaScriptCore,用於執行對js的解析。同時,原生端提供的各種Native Module(如網路請求,ViewGroup控制元件模組)和JS端提供的各種JS Module(如JS EventEmiter模組)都會在C++實現的so檔案中儲存起來,最終通過C++層中的儲存的對映實現兩端的互動。

在這裡插入圖片描述

在RN開發過程中,大多數情況下開發人員並不需要需要了解RN框架的具體細節,只需要專注JS端的邏輯程式碼實現即可。但是需要注意的是,由於js程式碼是執行在獨立的JS執行緒中,所以在js中不能處理耗時的操作,如fetch、圖片載入和資料持久化等操作。

最終,JS程式碼會被打包成一個bundle檔案並自動新增到應用程式的資源目錄下,而應用程式最終載入的也是打包後的bundle檔案。RN的打包指令碼位於“/node_modules/react-native/local-cli”目錄下,打包後通過metro模組壓縮成bundle檔案,而bundle檔案只包含打包js的程式碼,並不包含圖片、多媒體等靜態資源,而打包後的靜態資源會是被拷貝到對應的平臺資原始檔夾中。

總的來說,RN使用Javascript來編寫應用程式,然後呼叫原生元件執行頁面渲染操作,在提高了開發效率的同時又保留了Native的使用者體驗。並且,伴隨著Facebook重構RN工作的完成,RN也將變得更快、更輕量、效能更好。

Weex

作為一套前端跨平臺技術框架,Weex建立了一套原始碼轉換以及Native與Js通訊的機制。Weex表面上是一個客戶端框架,但實際上它串聯起了從本地開發、雲端部署到分發的整個鏈路。 具體來說,在開發階段編寫一個.we檔案,然後使用Weex提供的weex-toolkit轉換工具將.we檔案轉換為JS bundle,並將生成的JS bundle上傳部署到雲端,最後通過網路請求或預下發的方式載入至使用者的移動應用客戶端。當整合了Weex SDK的客戶端接收到JS bundle檔案後,呼叫本地的JavaScript引擎執行環境執行相應的JS bundle,並將執行過程中產生的各種命令傳送到native端進行介面渲染、資料儲存、網路通訊以及使用者互動響應。

在這裡插入圖片描述
由上圖可知,Weex框架中最核心的部分就是JavaScript Runtime。具體來說,當需要執行渲染操作時,在iOS環境下選擇基於JavaScriptCore核心的iOS系統提供的JSContext,在Android環境下使用基於JavaScriptCore核心的JavaScript引擎。

當JS bundle從伺服器下載完成之後,Weex的Android、iOS和H5會執行一個JavaScript引擎來執行JS bundle,同時向各終端的渲染層傳送渲染指令,並排程客戶端的渲染引擎實現檢視渲染、事件繫結和處理使用者互動等操作。 由於Android、iOS和H5等終端最終使用的是native渲染引擎,也就是說使用同一套程式碼在不同終端上展示的樣式是相同的,並且Weex使用native引擎渲染的是native元件,所以在效能上比傳統的WebView方案要好很多。

當然,儘管Weex已經提供了開發者所需要的最常用的元件和模組,但面對豐富多樣的移動應用研發需求,這些常用基礎元件還是遠遠不能滿足開發的需要,因此Weex提供了靈活自由的擴充套件能力,開發者可以根據自身的情況定製屬於自己客戶端的元件和模組,從而豐富Weex生態。

Flutter

Flutter是Google開源的移動跨平臺框架,其歷史最早可以追溯到2015年的Sky專案,該專案可以同時執行在Android、iOS和fuchsia等包含Dart虛擬機器的平臺上,並且效能無限接近原生。相較於RN和Weex使用Javascript作為程式語言與使用平臺自身引擎渲染介面不同,Flutter直接選擇2D繪圖引擎庫skia來渲染介面。

在這裡插入圖片描述
如上圖所示,Flutter框架主要由Framework和Engine層組成,而我們基於Framework開發App最終會執行在Engine上。其中,Engine是Flutter提供的獨立虛擬機器,正是由於它的存在Flutter程式才能執行在不同的平臺上,實現跨平臺執行的能力。 與RN和Weex使用原生控制元件渲染介面不同,Flutter並不需要使用原生控制元件來渲染介面,而是使用Engine來繪製Widget(Flutter顯示單元),並且Dart程式碼會通過AOT編譯為平臺的原生程式碼,實現與平臺的直接通訊,不需要JS引擎的橋接,也不需要原生平臺的Dalvik虛擬機器,如圖1-5所示。 同時,Flutter的Widget採用現代響應式框架來構建,而Widget是不可變的,僅支援一幀,並且每一幀上的內容不能直接更新,需要通過Widget的狀態來間接更新。在Flutter中,無狀態和有狀態Widget的核心特性是相同的,檢視的每一幀Flutter都會重新構建,通過State物件Flutter就可以跨幀儲存狀態資料並恢復它。

在這裡插入圖片描述
總的來說,Flutter是目前跨平臺開發中最好的方案,它以一套程式碼即可生成Android和iOS平臺兩種應用,很大程度上減少了App開發和維護的成本,同時Dart語言強大的效能表現和豐富的特性,也使得跨平臺開發變得更加便利。而不足的是,Flutter還處於Alpha階段,許多功能還不是特別完善,而全新的Dart語言也帶來了學習上的成本,如果想要完全替代Android和iOS開發還有比較長的路要走。

PWA

PWA,全稱Progressive Web App,是Google在2015年提出漸進式的網頁技術。PWA結合了一系列的現代Web技術,並使用多種技術來增強Web App的功能,最終可以讓網頁應用呈現和原生應用相似的體驗。

相比於傳統的網頁技術,漸進式Web技術是可以橫跨Web技術及Native APP開發的技術解決方案,具有可靠、快速且可參與等諸多特點。

具體來說,當使用者從手機主螢幕啟動時,不用考慮網路的狀態就可以立刻載入出PWA。並且,相比傳統的網頁載入速度,PWA的載入速度是非常快的,因為PWA使用了Service Worker 等先進技術。除此之外,PWA還可以被新增在使用者的主螢幕上,不用從應用商店進行下載即可通過網路應用程式Manifest file提供類似於APP的使用體驗。

作為一種全新Web技術方案,PWA的正常工作需要一些重要的技術元件,它們協同工作併為傳統的Web應用程式注入活力,如圖1-8所示。

在這裡插入圖片描述
其中,Service Worker表示離線快取檔案,其本質是Web應用程式與瀏覽器之間的代理伺服器,可以在網路可用時作為瀏覽器和網路間的代理,也可以在離線或者網路極差的環境下使用離線的緩衝檔案。

Manifest則是W3C一個技術規範,它定義了基於JSON的清單,為開發人員提供一個放置與Web應用程式關聯的後設資料的集中地點。Manifest是PWA 開發中的重要一環,它為開發人員控制應用程式提供了可能。

目前,漸進式Web應用還處於起步階段,使用的廠商也是諸如Twitter、淘寶、微博等大平臺。不過,PWA作為Google主推的一項技術標準,Edge、Safari和FireFox等主流瀏覽器也都開始支援漸進式Web應用。因此,可以預見的是,PWA必將成為繼移動之後的又一革命性技術方案。

對比

在當前諸多的跨平臺方案中,RN、Weex和Flutter無疑是最優秀的。而從不同的細節來看,三大跨平臺框架又有各自的優點和缺點,可以通過表1-1來檢視。

對比型別 React Native Weex Flutter
支援平臺 Android/IOS Android/IOS/Web Android/IOS
實現技術 JavaScript JavaScript 原生編碼/渲染
引擎 JS V8 JSCore Flutter Engine
程式語言 React Vue Dart
bundle包大小 單一、較大 較小、多頁面 不需要
框架程度 較重 較輕
社群 活躍、FB維護 不活躍 活躍

如上表所示,RN、Weex採用的技術方案大體相同,它們都使用JavaScript作為程式語言,然後通過中間層轉換為原生的元件後再利用Native渲染引擎執行渲染操作。而Flutter直接使用skia來渲染檢視,而Flutter Widget則使用現代響應式框架來構建,和平臺沒有直接的關係。就目前跨平臺技術來看,JavaScript在跨平臺開發中可謂佔據半壁江山,大有“一統天下”的趨勢。 從效能方面來說,Flutter的效能理論上是最好的,RN和Weex次之,並且都好於傳統的WebView方案。但從目前的實際應用來看卻並沒有太大的差距,特別是和0.5.0版本以上的RN對比效能體驗上差異並不明顯。 而從社群和社群的活躍來看,RN和Flutter無疑是最活躍的,RN經過4年多的發展已經成長為跨平臺開發的實際領導者,並擁有各類豐富的第三方庫和開發群體。Flutter作為最近才火起來的跨平臺技術方案,不過目前還處在beta階段,商用的例項也很少,不過應該看到google的號召力一直是很強,未來究竟如何發展讓我們拭目以待。

示例

eros-yanxuan

簡介

eros-yanxuan 是基於 eros 開發的Weex專案,部分頁面參考了專案網易嚴選 weex 版本,歡迎star或fork。

執行

確保你本地已經整合了 eros 開發所需的環境

clone 專案到本地:

$ git clone https://github.com/xiangzhihong/eros-yanxuan.git
複製程式碼

進入目錄,下載前端所需的依賴:

$ cd eros-yanxuan
$ npm install
複製程式碼

iOS SDK

開啟platforms目錄下的WeexEros專案,在WeexEros中使用pod新增依賴。

$ cd platforms/ios/WeexEros
$ pod update                // 下載 iOS 依賴
$ open WeexEros.xcworkspace // 自動開啟專案
複製程式碼

選中模擬器,點選綠色箭頭執行 app 即可。

Android

對於Android工程來說,使用Android Studio開啟platforms目錄下的WeexFrameworkWrapper的Android工程,然後使用install.sh安裝Android工程的需要依賴包nexus和wxframework。

具體可以參考自行匯入專案,便可執行起來。

執行

  • 專案根目錄下執行 eros dev
  • 關閉除錯,攔截器,開啟熱更新
  • 重新 build app

效果

在這裡插入圖片描述

Question

執行過程中出現問題在以下地址解決方法,如果沒有找到,可以參考eros快速入門新建一個Weex工程,然後將src和配置檔案的程式碼拷貝過去。 如果還有問題,請加群:515980159

相關文章