寫在前面
2018 年,Airbnb 放棄了繼續(xù)使用 React Native,個中原因主要有兩方面:
- 技術(shù):成熟度、配套設(shè)施/類庫建設(shè)成本、首屏性能硬傷等沒能很好地解決
- 團隊組織:工程師要求高、跨技術(shù)棧/跨團隊調(diào)試/測試等也產(chǎn)生了新的問題
實際上,跨端方案遭遇的問題遠不止這些,一些時候 Write Once, Run Everywhere 只是美好愿景
一.技術(shù)困境
一言以蔽之,觸碰到能力邊界之前,跨端方案里的一切都是美好的
以 React Native 為例:
Bridge 層通過消息通信將 JAVAScript 世界與 Native 世界聯(lián)系起來
Shadow Tree 用來定義 UI 效果及交互功能,Native Modules 提供 Native 功能(比如藍牙),二者之間通過 JSON 消息相互通信
P.S.圖有些舊,但不影響理解原理,更新的 React Native 架構(gòu)圖見 React Native 架構(gòu)演進
在這樣的技術(shù)架構(gòu)中,寫的和實際執(zhí)行的都是 JavaScript,調(diào)用由 Native 提供的視圖渲染能力及平臺特定能力,F(xiàn)acebook 稱之為Scripting native 方案,姑且叫做容器化 Native 跨端方案:
將 Native App 改造成標準化的容器,進而允許一套代碼跨多端標準容器運行,如 React Native/Weex、Flutter
(摘自移動端跨平臺技術(shù)之下的變與不變)
容器能力在很大程度上決定著開發(fā)效率,在容器提供了一致的標準支持范圍內(nèi),能夠愉快地一人搞定多端。
然而,一旦觸及能力邊界,就會面臨高成本的多層聯(lián)合開發(fā)(Native 層、JavaScript 引擎層、特定業(yè)務(wù)領(lǐng)域?qū)印I(yè)務(wù)層……),人效上并沒有優(yōu)勢。另一方面,如何保持多端一致性,也是個極其復(fù)雜并且充滿技術(shù)挑戰(zhàn)的問題
此外,相關(guān)的配套能力也直接關(guān)系到開發(fā)效率:
- 調(diào)試:跨技術(shù)棧調(diào)試一直是難題,問題排查成本越來越高
- 性能:跨線程、跨頁面耗時分析困難、性能工具鏈缺失
- 工程鏈路:由于技術(shù)方案的特殊性,需要量身定制許多配套設(shè)施(包括但不限于 IDE、調(diào)試、性能、CI/CD、監(jiān)控),才能將各個環(huán)節(jié)的成本降下來
總的來說,技術(shù)上最大的困境在于:
- 抹不平的多端差異
- 掀不開的 JavaScript 引擎蓋
- 跟不上的配套能力
多端一致性在技術(shù)投入上幾乎是無底洞,底層的平臺架構(gòu)差異(UI 渲染方式、事件機制、系統(tǒng) API)根深蒂固,以各類跨端方案目前的成熟度僅能覆蓋極其有限的一部分,留有非常大的空白需要通過擴展容器能力來填補,包括通用的基礎(chǔ)能力(如 UI、交互),以及面向業(yè)務(wù)領(lǐng)域的特定能力(如多媒體、定位)
引入 JavaScript 引擎雖然獲得了動態(tài)執(zhí)行代碼的能力,但也帶來了技術(shù)上的不確定性,幾乎無法跟蹤解決 JavaScript 引擎內(nèi)部的崩潰或異常行為
通用的基礎(chǔ)設(shè)施大多無法直接用于跨端場景,邊邊角角的配套能力都需要花力氣建設(shè),而為了滿足業(yè)務(wù)快速生長,總是優(yōu)先建設(shè)核心關(guān)鍵能力,配套支持通常是滯后的,同樣影響著效率
Flutter 能帶來一些不同嗎?
事實上,F(xiàn)lutter(目前看起來)同樣面臨這些技術(shù)困境,技術(shù)實現(xiàn)的變化并未徹底改變局面
據(jù) 2020 Q1 調(diào)查結(jié)果,F(xiàn)lutter 開發(fā)者認為最重要的 6 個問題是:
- 調(diào)試錯誤和崩潰
- 測試確保 App 能夠跨多平臺運行
- 選用狀態(tài)管理方案
- 理解和處理布局問題(如文本溢出)
- 根據(jù)設(shè)計稿創(chuàng)建 UI
- 排查特定平臺問題
同時,認為最困難的 6 個問題是:
- 排查特定平臺問題
- 內(nèi)存問題的診斷和修復(fù)
- CPU 使用率問題的診斷和修復(fù)
- 接入現(xiàn)有的 Native API
- UI 卡頓問題的診斷和修復(fù)
- 開發(fā)特定平臺的 Flutter 插件
因此,跨端方案的調(diào)試、性能之痛仍在 Flutter 延續(xù),多端差異以及配套能力的困境并沒有改變
二.團隊組織困境
與單端開發(fā)模式相比,跨端方案的協(xié)作成本更高,體現(xiàn)在:
- 跨團隊
- 鏈路長
- 容器團隊壓力大
- 職責邊界不清晰
跨端方案下,跨團隊協(xié)作成為了最主要的協(xié)作方式,需求串講、開發(fā)、聯(lián)調(diào)、問題排查等多個環(huán)節(jié)都需要跨團隊溝通/協(xié)作,溝通成本不容忽視
長鏈路意味著技術(shù)細節(jié)散落在多層,各自只擁有一小部分知識:
表層業(yè)務(wù)邏輯
-----------------------------
特定業(yè)務(wù)領(lǐng)域框架
-----------------------------
通用前端框架/類庫
-----------------------------
JavaScript引擎(擴展)
-----------------------------
Native Module | 特定業(yè)務(wù)領(lǐng)域能力
-----------------------------
Native通用框架
-----------------------------
Native View
-----------------------------
平臺操作系統(tǒng)
由于每個團隊都看不到全景,每一個原因不那么顯而易見的問題就都要一層層向下排查,甚至涉及特定業(yè)務(wù)領(lǐng)域能力的部分又分為許多層……
另一方面,如此繁多的層次也造成了復(fù)雜度堆積,越往下層復(fù)雜度越高,因為不確定的可變輸入越多,越難弄明白來龍去脈,排查問題的成本也越高
理想情況下,按漏斗模型逐層過濾,每一層只需要檢查自己的輸入輸出,但滯后的配套能力讓表層業(yè)務(wù)難以識別出問題所在的范圍,于是容器團隊成為了問題流轉(zhuǎn)的過濾閥,上接紛繁的 JavaScript 業(yè)務(wù),下連復(fù)雜的特定領(lǐng)域能力,大量的時間耗費在了弄清楚來龍去脈上,容器能力擴展被迫降速,反復(fù)排查已知問題……
業(yè)務(wù)視角下,對業(yè)務(wù)之下的層次職責劃分并不十分清楚,因此很容易找錯層/人,產(chǎn)生無效的“重定向”。而容器層同樣也不具備全景視圖,問題流轉(zhuǎn)軌跡變得相當曲折,溝通成本充斥在各個環(huán)節(jié)中,制約著開發(fā)效率
三.個體困境
對個體而言,面臨的最大困難是跨端方案與 Web 標準存在些許差異,并且這些許差異不像 W3C 標準一樣能寫得清清楚楚:
Weex enables developers to use modern web development skills to build Android, IOS, and Web apps with a single codebase.
也就是說,通用的 Web 經(jīng)驗不完全適用,學習曲線并不十分友好,例如:
- rem、媒體查詢、scale/zoom等適配經(jīng)驗都不一定適用
- 減少 DOM 操作、合并 JavaScript 文件、開啟硬件加速等常規(guī)優(yōu)化措施也不一定能產(chǎn)生明顯的性能優(yōu)化效果
- (像學習 Web 一樣)只了解瀏覽器之上的標準能力是不夠的,想要真正高效地完成業(yè)務(wù)開發(fā)工作,容器原理甚至部分實現(xiàn)細節(jié)都要理解
就像有 Native 背景的開發(fā)者學習TypeScript一樣,初接觸無師自通,熟悉的Class、Interface、靜態(tài)類型用起來游刃有余……然而,熟知 TypeScript 的開發(fā)者一定知道個中細節(jié)存在著多少奇怪的地方
四.跨端的真正意義是什么?
React Native 最初的出發(fā)點是:
希望 Native 開發(fā)也能像 Web 一樣 Move fast
快速迭代(Rapid iteration cycle):Web 一天兩版,產(chǎn)品迭代周期更短
快速反饋(Immediate testing feedback):Web 發(fā)布立即觸達用戶,A/B test 等實驗結(jié)果立等可取,產(chǎn)品演進更快
快速開發(fā)(Rapid development velocity):刷新瀏覽器即可生效,不必等待重新編譯 App
黯羽輕揚,公眾號:前端向后React Native 從誕生到現(xiàn)在
因此,從需求角度來看,開發(fā)效率是次要的,動態(tài)化的靈活性、快速迭代助業(yè)務(wù)先贏才是其跨端的主要意義,或者說追求的是生產(chǎn)效率,而不僅是開發(fā)效率,更短的迭代周期,更快速的觸達用戶都是直接的生產(chǎn)效率進步
然而,在三大困境之下,開發(fā)效率實際上也嚴重影響著生產(chǎn)效率,但還不足以抵消快速迭代、動態(tài)發(fā)布的重大進步,此消彼長也算是一種平衡,一種可接受的妥協(xié)
五.在困境中尋找生門
理想情況下,容器應(yīng)該是趨于標準化的,提供多端一致、豐富穩(wěn)定的能力支持,之上的業(yè)務(wù)棧極少觸及容器能力邊界,從而使得容器層能夠不斷優(yōu)化探索,更好地滿足業(yè)務(wù)發(fā)展的需要
另一方面,跨端方案只是將多端不一致性帶來的復(fù)雜度下沉到了容器層,獨立于平臺的語言環(huán)境(JavaScript 引擎、Dart 虛擬機等)能夠保證上層業(yè)務(wù)邏輯的一致性,但容器層仍然需要在多端各自實現(xiàn)一套,如何保證容器能力的多端一致性,仍然是個大問題,也并不比非跨端方案下容易多少
因此,首先要解決容器能力豐富度的問題,將邊界拓寬,從根源上減少問題。轉(zhuǎn)而集中火力到真正的難題上,攻下最有價值的難點部分。同時通過虛擬架構(gòu)等方式建立全職能的業(yè)務(wù)支撐團隊,降低溝通成本:
- 業(yè)務(wù)要有自研能力:化解下層資源瓶頸,共同豐富容器能力
- 專注必須花大力氣投入的點:調(diào)試能力、標準化、性能分析以及持續(xù)跟蹤、工程配套設(shè)施
- 要有全職能的業(yè)務(wù)支撐團隊:有能力兜住所有問題,真正提供一攬子解決方案,消除無意義的溝通重定向
其中,業(yè)務(wù)自研能力先要有標準的擴展方式,要求容器實現(xiàn)上易擴展,業(yè)務(wù)開發(fā)者不需要了解過多細節(jié)也能快速進入開發(fā)。調(diào)試能力在長鏈路的技術(shù)棧下至關(guān)重要,問題識別成本越低、準確率越高,效率越高,所能釋放出來的資源就越多
從業(yè)務(wù)開發(fā)角度來看,更需要的可能是一層網(wǎng)關(guān),請求過去響應(yīng)回來,而不是一系列路由表,需要一跳一跳地跟蹤。全職能的業(yè)務(wù)支撐團隊組成局域網(wǎng),讓網(wǎng)關(guān)之后的流量得以快速流轉(zhuǎn),高效協(xié)作的同時提升業(yè)務(wù)開發(fā)的幸福感
作者:黯羽輕揚 來源:前端向后