跨平台開發的背景
如果使用原生方式開發APP,就要求我們必須針對iOS和Android這兩個平台分别開發,這樣的話,我們就需要用不同的語言去實作同樣的功能,并承擔是以帶來的維護任務,這對于企業而言,付出的成本和時間會成倍增加。于是,跨平台的的概念走進了我們的視野。
本質上講,跨平台開發是為了增加業務代碼的複用率,減少因為要适配多個平台所帶來的工作量,進而降低開發成本。一套代碼多端使用,這樣也能夠保證一緻的使用者體驗。
“一次代碼,到處運作”。二十多年前Java正是以跨平台特性的口号登場,擊敗了衆多競争對手。這個口号,意味着Java可以在任何平台上進行開發,然後編譯成一段标準的位元組碼後,就可以運作在任何裝有Java虛拟機(JVM)的裝置上。雖然現在跨平台已經不是Java最大的優勢(而是它繁榮的生态),但不可否認,當年它打着跨平台的旗号橫空出世确實是勢不可擋。
而對于移動端開發而言,如果能實作“一套代碼,多端運作”,這樣的技術勢必會引發新的生産力變革。在目前多終端時代的大環境下,可以為企業節省大量的人力資源,進而帶來直接的經濟效益。
跨平台開發方案的三個時代
<一>Web容器時代
web時代的方案,主要采用的是原生應用内嵌浏覽器控件WebView(iOS為UIWebView或者WKWebView,Android為WebView)的方式進行HTML5頁面渲染,并定義HTML5與原生代碼互動協定,将部分原生系統能力暴露給HTML5,進而擴充HTML5的邊界。這類互動協定,就是我們通常說的JS Bridge(橋接)。
這種開發模式既有原生代碼,又有web應用代碼,是以又被稱為Hybrid開發模式。
由于HTML5代碼隻需要開發一次,就能在多個系統運作,是以大大降低了開發成本。并且Web開發技術的社群和資源都十分豐富,是以開發效率也比較高。但是,一個完整的HTML5頁面的展示要經曆浏覽器控件的加載、解析和渲染三大過程,性能消耗要比原生開發增加N個數量級。
Hybrid開發方案,有其優勢也有其缺點,總體而言,瑕不掩瑜。實際上,Hybrid開發方案是跨平台曆史上最成功的例子!
最後,給一張Hybrid開發架構的流程圖吧:

<二>泛Web容器時代
Web容器方案具有生态繁榮、開發效率高、跨平台相容性強等優勢,但是它最大的問題在于承載着大量Web标準的Web容器過于笨重,以至于性能和體驗與原生有較大差距。
而在實際的産品功能研發中,我們通常隻會用到Web标準中很小的一部分。面對這樣的現實,我們很快就想到:能否對笨重的Web容器進行功能裁剪,在僅保留必要的Web标準和渲染能力的基礎上,使得友好的開發體驗與穩定的渲染性能保持一個平衡?
答案當然是可以的。
泛Web容器時代的解決方案優化了Web容器時代的加載、解析和渲染這三大過程,把影響他們獨立運作的Web标準進行了裁剪,以相對簡單的方式支援了建構移動端頁面必要的Web标準;同時,這個時代的解決方案基本上完全放棄了浏覽器控件渲染,而是由原生接管繪制。也就是說,将原生系統作為渲染的後端,為依托于JavaScript虛拟機的JavaScript代碼提供所需的原生UI控件的實體,是以最終都是通過原生系統來進行渲染的。
泛Web時代的代表架構有React Native、Weex等,其架構如下:
<三>自繪引擎時代
泛Web容器時代使用原生控件承載界面渲染,固然解決了不少性能問題,但是當原生系統版本以及原生API變化的時候,我們需要處理不同平台的原生渲染能力的差異、修複各類奇奇怪怪的Bug。
而這一時期的Flutter則開辟了一種全新的思路,即從頭到尾重寫一套跨平台的UI架構,包括渲染邏輯,甚至是開發語言。
- 渲染引擎依靠跨平台的Skia圖形庫來實作,Skia引擎會将使用Dart建構的抽象的視圖結構資料加工成GPU資料,交由OpenGL最終提供給GPU渲染,至此完成渲染閉環,是以可以在最大程度上保證一款應用在不同平台、不同裝置上的體驗一緻性。
- 而開發語言選用的是同時支援JIT(JustInTime,即時編譯)和AOT(AheadOfTime,預編譯)的Dart,不僅保證了開發調試效率,也提升了執行性能。
是以,Flutter不僅可以減少不同平台間的差異,而且還可以保持和原生開發一樣的高性能,正因如此,Flutter成為了目前最受關注的架構。
自繪引擎開發架構的原理圖如下:
該選擇哪一類跨平台開發方案
在不同角度上來看,三個時代的跨平台方案代表們在開發效率、渲染性能、維護成本以及社群生态上各有優劣,如下圖所示:
我們在做技術選型時,可以參考以上次元,從開發效率、技術棧、性能表現、維護成本以及社群生态來進行綜合考慮。比如,是否必須支援動态化(動态化指的是,代碼邏輯放到雲端,以下發的方式更新應用程式的原本功能)?是隻解決Android、iOS的跨端問題,還是也要包括Web?對性能要求如何?對多端體驗的絕對一緻性和維護成本是否有強訴求?
從各個次元綜合考量,Flutter和ReactNative無疑是最均衡的兩種跨端方案,而其他的方案或多或少都“偏科”嚴重。
- React Native依托于Facebook,經過4年多的發展已經成長為跨平台開發領域實際的上司者,并擁有較為豐富的第三方庫和開發社群。
- Flutter以挑戰者姿态出現在我們面前,可以提供更徹底的跨平台解決方案,再加上Google的強大号召力,Flutter的未來可期。
那麼我究竟是選擇ReactNative還是Flutter呢?
對于知識學習而言,這兩個應用層面的架構最好都學。Flutter作為後來者,其實它從RN社群借鑒了不少的優秀設計,很多概念兩邊都有對應,比如RN的component和Flutter的widget、Flex布局思想、狀态管理和函數式程式設計等等,這類的知識都是兩個架構通用的技術。未來也許還會出現新的解決方案,老架構也會不斷更新,隻有掌握核心原理才能真正立于不敗之地。
對于實際項目而言,這兩個架構都已經達到了大面積商用的标準。綜合成熟度和生态,目前而言RN略勝于Flutter。是以如果是中短期的小項目的話,目前選擇RN可能會更好。但是作為技術選型,我們看的要更遠一些。Flutter在設計理念、渲染能力的一緻性以及性能表現上,與RN相比都優勢明顯。
此外,Flutter的野心不止移動端。前段時間,Google團隊已經完成了Hummingbird,即Flutter的Web官方Demo,在桌面作業系統的探索上也取得了一定進展,未來大前端技術棧是否會由Flutter完成統一,值得期待。
小結
在不同的平台上開發和維護同一個産品,所付出的成本一直以來都令各企業頭疼,于是各類跨端開發方案應運而生。從Hybrid開發的Web容器時代,到以RN、Weex為代表的泛Web容器時代,再到以flutter為代表的自繪引擎時代,這些優秀的跨平台開發架構們慢慢抹平了各平台的差異,使得作業系統的邊界越來越模糊。
另外需要補充的一點是,Flutter在實際上本身是不支援熱更新的,但是我們可以另辟蹊徑的。比如,我們可以将一些常見的活動封裝成模闆,讓後端配置不同的模闆就可以實作動态化了。另外,業界已經有一些通過JSCore實作的Flutter動态布局的實踐了,預計不久就會有一些成熟的方案出現。