一.跨平台,是想跨哪些平台?
目前(2020/7/18)來看,移動端跨平台需求主要集中在:
-
跨 PC 端與移動端:PC 向無線過渡的早期,希望 PC Web 與移動 Web 復用同一套代碼
-
跨 Native 與 Web:商品詳情頁等要求有一套功能差不多的 Web 頁能夠在端外訪問,需要跨 Native App 與 Web
-
跨 Native 雙端:出於開發效率等原因,希望 Android、iOS 雙端復用一套業務代碼
-
跨 App:一些產品功能期望能在多個渠道投放上線,以工具類需求為主,如打車、買票、點餐
在可預見的未來,可能還會有這些跨平台需求:
-
跨輕應用:系統級即用即走的輕量級應用,如Android 快應用、iOS App Clips
-
跨 IoT 設備:各種有顯示屏的設備都會成為新的“端”,如車載設備、智能家居
-
跨一切客戶端:可能是偽需求,同一產品在不同平台的側重點不同,或許並不需要把所有功能完整地搬到各式各樣的客戶端設備/平台渠道上,例如快應用與 Native App 的定位顯然不一樣
在這樣的時代背景下,無論從資源成本、開發效率,還是從產品迭代、技術演進的角度來看,跨平台開發都是強需求,所以才有了層出不窮的各種跨平台方案探索
二.層出不窮的跨平台技術
細數近幾年業界主流的移動端跨平台方案,可大致分為 3 類:
-
Web 生而跨平台:只要有瀏覽器或 WebView,依托 Web 技術即可輕松跨平台,如 Web App、PWA(Progressive Web Apps)、Hybrid App、PHA(Progress Hybrid App)
-
容器化 Native 跨端:將 Native App 改造成標准化的容器,進而允許一套代碼跨多端標准容器運行,如 React Native/Weex、Flutter
-
小程序一碼多投跨 App:國內市場中,越來越多的超級 App 支持了小程序,但各自的小程序框架並沒有統一標准,於是有了Taro、kbone、uni-app等一系列跨小程序框架的方案來滿足跨 App 投放產品功能的需求
跨平台:Web 與生俱來
跨平台是 Web 與生俱來的優勢,瀏覽器和 WebView 都是 W3C 規范下的標准化 Web 容器,因此 Web 頁面能夠輕松投放到端外瀏覽器、端內 WebView、以及其它 App 提供的 WebView 中
單從成本角度來看,Web 方案是跨平台的不二之選:
-
沒有額外的學習成本:一套基礎技術吃遍端內、端外、甚至 PC 瀏覽器、電視機頂盒
-
不依賴特殊的配套設施:開發、調試、構建、發布、監控、運維等所有工程化環節都是通用的
-
坐擁龐大的既有生態:npm 百萬模塊,應有盡有
-
Web 基於開放標准:走出去引進來都不是難事
並且,Web 本身就是一個平台,退可守,技術風險更低
但在另一些方面,依靠 Web 技術跨端也存在其局限性:
-
平台能力:受限於 Web 標准容器,無法滿足平台能力相關的需求,如相機、藍牙、多媒體等
-
體驗:移動端 Web 體驗遠不及 Native,主要體現在首屏加載慢、動畫卡頓、長頁滾動閃爍等場景
-
性能:內存消耗大、GPU 利用率低
加上 Web 標准更迭慢,新特性兼容性差(如Push API過去許多年了,仍然無法放心使用),Web 基礎能力難以滿足 Native 端的需求。因此,在傳統 Web App 的基礎上,展開了更多的探索:
-
PWA(Progressive Web Apps):離線緩存、系統通知、主屏圖標等類 Native App 能力加持之下的 Web App,但兼容性並不樂觀
-
Hybrid App:Web 與 Native 混合的方案,將由 Native 實現的平台能力(比如掃描二維碼)注入到 WebView 環境供 Web App 使用,以擴展 Web 的平台能力
-
PHA(Progressive Hybrid App):PWA 與 Hybrid 思想的結合,通過 Hybrid 手段讓 Web 的性能和體驗接近 Native
PWA 標准化似乎走不通,即便走通了能夠真正放心用起來可能也是數年之后了。Hybrid App 解決了一部分問題(平台能力擴展),但還不夠。PHA 是這兩種思路的延續,借助 Native 技術實現 PWA 的夢想
但無論 PHA 還是 HA,引入 Native 依賴都意味着 Web 開放性的損失,繼而帶來跨端、跨 App 方面的問題
跨端:容器化 Native
除 Web 天然跨端之外,另一種統一多端的思路是將 Native 定制成標准容器,讓同一份代碼跑在一個個標准容器中,例如:
-
Android 容器:Native 殼 App
-
iOS 容器:Native 殼 App
-
Web 容器:Web Runtime
React Native 跨 Android、iOS、Web、Windows 四端,Weex 跨 Android、iOS、Web 三端,Flutter 以類似的方式跨 Android、iOS、Web、Linux 四端
從技術角度來看,RN 與 Weex 在 Native 容器中提供了 JavaScript 運行環境,以及布局引擎,渲染層都采用 Native 控件,因此 UI 交互上仍然存在系統差異。而 Flutter 方案更徹底一些,連渲染層也換成了基於圖形引擎自繪 UI 控件,從而保證 UI 交互的跨端一致性
然而,由於容器化 Native 的方案是從 Native 出發,沒有跨端天賦,除了要想辦法支持 Web,還面臨一個更難解決的問題——跨 App
跨 App:小程序一碼多投
技術視角下,小程序跨 Native App 仍然是依靠 Web 方案,那么,為什么不直接用 Web App 呢?
由於商業競爭等因素,闖入別人家地盤的 Web App 通常會遭到一些限制,如安全警告、權限控制、甚至干脆禁止訪問(所以才有了口令分享等彎彎繞繞的方式)
小程序則不同,其初衷是開放的,歡迎大家入駐(當然,也要遵守規則),並且國內的許多大型 App 也都相繼開放了小程序能力,小程序逐漸成為跨 App 的正規方式。但小程序平台多起來之后,框架標准不統一的問題也暴露了出來,都叫小程序,但都大同小異,於是,如何快速產出多種小程序變成了一個值得探索的技術課題
實現原理上分為兩種,編譯轉換與運行時適配,前者能夠達到等同於原生小程序的性能但帶來了諸多限制(編譯期難以識別的寫法都不支持),現有的 Web App 不那么容易遷移成跨 App 小程序,例如 Taro、uni-app 等。后者犧牲性能換取了更多的可能性,現有的 Web App 能夠相對容易地遷移過來,例如 Taro Next、kbone 等
P.S.當然,也可以有動靜結合的思路,理想情況下,絕大多數基礎業務走運行時平遷,個別高性能要求的部分走編譯轉換
三.重重變化之中,什么才是不變量?
渠道/端/平台、業務代碼、工程化配套設施似乎都在快速地發生變化,沒有哪個是穩定不變的
既然全都在變,就換個角度看,哪個部分一定會發生變化?
-
容器:新的渠道/端/平台都是新的容器
-
跨容器技術:新容器的出現,意味着新的跨容器技術要求
哪個部分是不必要跟着變的?
-
業務代碼:技術方案的更迭、新渠道/端/平台的出現,通常伴隨着業務代碼的遷移,Native 切 React Native 切 Flutter……樂此不疲,但從成本上看,業務代碼並不一定也並不應該跟着變
-
工程化配套設施:大多與技術棧強相關,例如 Web App 的開發、調試、構建、發布、監控、運維與 Native App 存在諸多差異,但其中更基礎的部分是技術無關,而流程相關的,例如構建-發布流程、監控運維服務等並不需要跟着變
-
容器中的平台能力:無論何種跨容器的方案,平台能力擴展需求都是一致的,對應的 Native 模塊封裝不應該跟着變
業務代碼遷移的成本是非常高的(涉及技術棧變化時更痛),配套設施的推倒重建也絕對是大工程,那么,有沒有辦法把這些不應該跟着變的部分固定下來?
有,將變化的部分抽象出去。依賴抽象而不依賴具體,上層就不用跟着變了:
標准框架 \ --------- | 配套設施 標准容器 /
在這樣的抽象模型下,上層業務代碼依賴標准業務框架,而不直接依賴容器能力,從而允許業務框架以下的部分能夠替換。業務框架依賴抽象的標准容器,而不與具體的特定容器相綁定,可替換為遵循容器標准的其它容器
基於標准框架,能夠提供配套的腳手架、組件庫、可視化搭建等配套開發工具。基於標准容器,能夠建立性能診斷、事件追蹤等配套調試能力,從而覆蓋到工程化的整個鏈路,配套設施也幾乎不用跟着變了
至於平台能力擴展,作為標准容器中的重要部分,也應該抽象出標准 API(類比瀏覽器提供的 BOM 系 API),供上層業務使用
四.跨平台技術的未來
預見不到未來,所以這里拋出幾個可能性:
-
移動跨端只跨 Native 兩端:對許多移動產品而言,體驗細膩、性能優異的 Native App 仍是目前最重要的應用形態,並且雙端功能完全一致,同等重要,所以只跨 Android、iOS 兩端,統一移動端 Native 開發是相對合理的方案
-
小程序跨 App 自成一體:如果小程序不能真正標准化,跨 App 投放需求催生出的跨小程序框架方案就有必要存在
-
Web 仍是 Web,Hybrid 仍將持續:Web 特性更迭周期太長,移動設備的更迭太慢,等不及 Web 以年為單位的進化速度,依靠 Native 增強 Web 的 Hybrid 過渡方案很可能長期“過渡”下去
P.S.小程序已經在標准化進程中了,小程序框架成為標准化的容器也不是沒有可能,畢竟小程序框架不存在 WebView、瀏覽器一樣的慢周期阻力
不看好一招吃遍天下的跨全端的方案,因為無論 universal 組件還是 universal API 都是最小交集,無法滿足實際需要。並且,真的需要讓一套代碼運行在所有渠道、端、平台上嗎?
同一產品在不同平台的側重點不同,或許並不需要把所有功能完整地搬到各式各樣的客戶端設備/平台渠道上,例如快應用與 Native App 的定位顯然不一樣