根據(jù)公開的 2018 年移動互聯(lián)網(wǎng)行業(yè)分析報告,目前支付寶的月活躍用戶已經超過 QQ ,成為國內第二大 App。
支付寶一開始僅僅只是一個單體應用的工具型 App,讓用戶可以在手機完成支付寶相關的業(yè)務查詢和操作。2013 年后,支付寶逐步轉型為平臺型 App, 平臺型 App 具有服務化、模塊化、工具組件化的特點。這個時候支付寶的業(yè)務不僅僅是支付,還需要給客戶提供很多生活相關的服務,例如余額寶、繳電費等。2015 年后支付寶成長為超級 App,此時支付寶里面需要支持大量復雜的業(yè)務,同時開放自己的商業(yè)能力,用自己流量助力合作伙伴,因此整個 App 面臨開放、動態(tài)化、高可用的挑戰(zhàn),面對這些挑戰(zhàn),我們把它總結為以下三點:
如何應對復雜的業(yè)務協(xié)同?
如何滿足業(yè)務快速迭代的需求?
如何構建面向未來的開放生態(tài)?
利用 Hybrid App 架構,應對復雜的業(yè)務協(xié)同
App 的業(yè)務越來越復雜,不僅僅是內部業(yè)務,還包含了大量外部的合作伙伴。如果采用傳統(tǒng)的 App 開發(fā)方式很難應對日趨復雜的業(yè)務場景。
1.1 Hybrid 技術方案選型
在 Hybrid 技術方案選型方面,我們通過“開發(fā)成本、用戶體驗、動態(tài)性、復雜業(yè)務支持能力、研發(fā)難度”五個方面綜合考量。我們篩選出 HTML5、ReactNative/Weex、Flutter 作為備選,并將原生開發(fā)作為基準線完成對比。(考慮到近期 Flutter 的熱度持續(xù)走高,因此我們納入 Flutter 一并分析。)
首先我們從業(yè)務開發(fā)成本角度來看:
原生作為最基礎的開發(fā)模式,需要雙端都進行開發(fā),無疑成本是最高的;
其次是 ReactNative/Weex,即使是一次開發(fā),同時運行在雙端,但由于是 JS 轉成 Native 組件渲染,實際運行起來仍然存在些許差異,導致開發(fā)者在寫業(yè)務界面時,部分差異需要通過 Native 端定制開發(fā)來解決。整體而言,ReactNative/Weex 已幫助業(yè)務方大幅降低開發(fā)成本;
接下來是 Flutter,從業(yè)務開發(fā)的角度來說,F(xiàn)lutter 針對雙端對齊真的下了大功夫。在大多數(shù)場景下,Android 端開發(fā)完畢之后能無縫跑在 iOS 端,當然這和它自研的引擎有關。只不過 Flutter 需基于 Dart 語言開發(fā),因此對于開發(fā)者而言,部分老業(yè)務移植的工作量需考慮在內;
最后是 HTML5,帶著成熟的語言,成熟的開發(fā)模式,雙端幾乎一樣的表現(xiàn)等特性表明 HTML5 仍然是目前我們能落地的開發(fā)成本最低的方案。
接下來我們討論用戶體驗:
首先,原生的體驗毋庸置疑是最好的;
其次是自有渲染引擎的 Flutter,無論是性能還是控件的展現(xiàn)形式,可以說是不亞于原生的體驗;
接下來便是 ReactNative/Weex 方案,通過將前端代碼渲染成本地 Natvie 控件。在早期版本中,由于部分控件優(yōu)化不到位導致 App 卡頓,因此用戶體驗的表現(xiàn)不足;
最后是 HTML5,完全通過瀏覽器內核進行渲染,借助預置資源、內核優(yōu)化等技術,HTML5 可以做到接近原生的體驗,但總體性能仍有差異。
接著是動態(tài)性的支持:
在本文第二章節(jié)“離線包機制+發(fā)布平臺”,我們會從快速迭代的角度深度分析動態(tài)性在支撐高并發(fā)業(yè)務場景下的重要性。
首先,動態(tài)性最優(yōu)的就是 HTML5 方案:可以訪問在線頁面,服務端即時生效,也可以通過下發(fā)資源的方式,進行動態(tài)更新;
其次是 ReactNative/Weex 方案,通過一定的定制,開發(fā)者可以將前端包熱部署、熱更新。不過相較于 HTML5 具備的“在線+離線”的動態(tài)性,該方案仍然存在一定差距;
接下來是原生,Android/iOS 雙端均可以通過一些黑科技手段,進行動態(tài)更新,不過由于 iOS 政策禁止,因此在動態(tài)性上,原生方案暫時不推薦;
最后是 Flutter,雖然有很強大的熱重載機制,不過由于 Google 的限制,線上版本 iOS 無法做到熱更新,因此在動態(tài)性評估中將 Flutter 排在最后。
最后我們聊下各個方案的實現(xiàn)起來的研發(fā)難度:
這里我們暫時將 HTML5 放在第一位,因為做 HTML5 Hybrid 方案,離不開內核優(yōu)化,內核優(yōu)化就需要有一定內核研發(fā)能力,因此在開發(fā)者視角下 HTML5 研發(fā)難度最高。如果只是單純的 HTML5 容器,研發(fā)難度就會大幅降低;
其次是 Flutter,目前在實際業(yè)務應用案例方面,國內較大體量的 App 暫時只有閑魚團隊引用了 Flutter;同時在 Flutter 的 GitHub 中仍然存在大量的 Open Issues 等待解決。而在實戰(zhàn)開發(fā)運用過程中,F(xiàn)lutter 的生命周期管理,視圖棧管理,原生頁面切換等問題都需要開發(fā)者在前期選型過程中便要重視;
接下來是 ReactNative/Weex,由于這兩個方案開源,且有大量成熟的技術社區(qū)支持,方案的研發(fā)難度對于開發(fā)者而言并不高,同時開源代碼方便修改,更容易上手;
最后是原生方案,如果不考慮做熱修復的話,原生方案無需做任何改動,直接使用即可;若考慮熱修復方案,目前市面也有一些成熟的開源熱修復方案可以直接使用。
綜上所述,我們再考慮了各方的優(yōu)劣之后,決定采用“HTML5 容器+內核優(yōu)化”的方式來應對復雜業(yè)務的開發(fā)問題。接下來我們就介紹下容器的架構。
1.2 容器架構
最上層是原生的 HTML5 代碼,這塊就是大家常見的 Web 開發(fā)環(huán)境,包括 HTML、CSS、JavaScript等。
下面一層即離線包管理,這個我們在第二章節(jié)內進行詳細介紹。
再往下是 HTML5 容器層,HTML5 容器作為中間層,將瀏覽器和支付寶底層框架有機結合起來,同時還提供各種生命周期機制、事件機制、擴展插件等內容。
在 HTML5 容器里面有個非常重要的概念: JSBridge。通過 JSBridge,HTML5 容器將支付寶框架底層以及中間件層提供的各種能力和 HTML5 前端代碼進行聯(lián)通,其中包括 RPC(遠程過程調用,用來實現(xiàn) App 和服務器通信)、支付、掃一掃等。
最下面是支付寶底層框架,提供微應用,微服務等概念。一個 HTML5 應用,也會被框架模擬成一個微應用,通過應用 ID 進行解耦。
1.2.1 JSBridge 介紹
JSBridge 是 HTML5 容器的基石,橋接了 JS 環(huán)境與 Native,實現(xiàn)了 Native 代碼和瀏覽器環(huán)境的雙向通信,Native 代碼可以通過調用瀏覽器提供的接口運行JS,從而實現(xiàn)調用 JS 函數(shù)、傳遞參數(shù)到 JS 環(huán)境等;而瀏覽器到JS環(huán)境的通信是通過 Native 攔截瀏覽器的請求來實現(xiàn),請求可以是網(wǎng)絡請求或者是一些內部函數(shù)的調用。
1.2.2 H5 容器定制化擴展
HTML5 容器提供了 2 種擴展方式:
JSAPI
JSAPI 方式給 HTML5 頁面增加了 Native 功能調用接口,通過實現(xiàn)自定義 JSAPI 類中的 Handler 方式,可以以 Native 的形式實現(xiàn)特定功能,例如調用 Native 加密函數(shù)。
事件
HTML5 容器在狀態(tài)變化時會發(fā)送事件,通過監(jiān)聽 HTML5 容器特定事件,可以實現(xiàn)對 HTML5 容器生命周期的處理,比如修改加載進度條顏色、修改頁面導航欄等。事件提供了更強的定制性,完全可以滿足對 HTML5 容器的各種自定義需求
1.3 容器穩(wěn)定性
上面在研發(fā)難度中,我們提及到了,HTML5 方式的研發(fā)難度是最高的,因為需要定制化內核進行性能及穩(wěn)定性優(yōu)化。目前支付寶采用的是阿里集團的 UC 自研內核,并針對支付寶的 HTML5 容器進行了深度優(yōu)化和定制。如圖所示,UC 內核和系統(tǒng)內核的卡頓卡死率的數(shù)據(jù)對比效果非常顯著,我們可以直觀地看到 Webview 穩(wěn)定性的提升。
離線包機制+發(fā)布平臺,滿足業(yè)務即時更新
目前支付寶業(yè)務的另外一個特點就是需要快速迭代,變化的政策、突發(fā)事件都需要我們可以快速把新的業(yè)務需求觸達給用戶。但是對于 App 開發(fā)者有一個不容忽視的問題,就是應用商店審核。由于審核的存在,App 上開發(fā)的業(yè)務會有一個統(tǒng)一排期,比如說月底會有新版本,那么所有的業(yè)務進度都得考慮 App 的排期計劃。
2.1 離線包機制
為了做到良好的用戶體驗,我們在容器中引入了離線包機制。通過離線包機制,我們將原有從線上加載的 HTML5 應用,提前下發(fā)到本地,通過讀取 IO,或者是內存,進行頁面的渲染,達到接近原生的用戶體驗。
通過發(fā)布平臺,我們可以將不同的 HTML5 離線包,以單獨應用的形式,進行不同維度的下發(fā),使原來 all in 的 Native 發(fā)布模式,改為各業(yè)務線自行定制發(fā)布計劃,自行制定發(fā)布標準,自行發(fā)布的并行發(fā)布形式,來滿足業(yè)務的快速迭代。
2.1.1 加載機制
通過內存提前加載,定時更新,啟動預加載內存等手段,我們將一個業(yè)務包需要用到的資源加載到內存,從而使啟動過程盡量無感知,頁面秒開無白屏。同時,我們還有 Fallback 手段,保證在包損壞或者是未下載完成時,可以通過在線頁面的形式,保證業(yè)務的 100% 可用性。
2.1.2 公共資源包機制
所謂公共資源包,即所有 HTML5 離線包都可能會用到的公共資源的集合。公共資源包解決多個 HTML5 應用使用同一資源產生的冗余問題。如 React 應用使用 ReactJS 框架代碼。您可以將公共資源放入全局資源包,以降低 HTML5 應用體積。
通過公共資源包機制,可有效降低各 HTML5 應用的包體積,從而使更新率提高,頁面開啟速度加快。
2.2 發(fā)布平臺
為了滿足快速迭代的需求,一個強大的發(fā)布平臺也是必不可少的。發(fā)布平臺的核心指標,就是將發(fā)布內容高效、精準的投放到指定的設備上,為了實現(xiàn)這個目標,我們做了如下的努力。
2.2.1 離線包大小管控及差量包機制
HTML5 容器離線包提供了更新機制,以單個離線包作為更新維度。因為單個離線包業(yè)務很簡單,所以離線包的大小是可控的,通常小于 500KB。我們通過大量的實踐,總結出來“500KB”這個值,既可以滿足單個業(yè)務的內容,也可以更高效地發(fā)布到設備上。500KB,在 4G 的時代,幾乎可以做到用戶無感知更新,即便是 2G/3G 也可以保證一個高的到達率。
上面說的是一個 HTML5 應用的大小。實際上,我們更新的包會更小,發(fā)布平臺會通過 diff 算法,計算出相同 HTML5 應用兩個不同的版本的差量包,差量包通常也就在幾 KB 至幾十 KB 不等,可以做到更高的下載成功率,下載成功率一定程度就意味著實際到達率。
2.2.2 Fallback 機制
在一些極端網(wǎng)絡場景下,新的業(yè)務資源包更新失敗,而我們又期望用戶使用的是最新的業(yè)務,這個時候 Fallback 訪問機制就會發(fā)揮作用。每個離線包資源都會在發(fā)布服平臺上存放一份,在剛剛說到的極端場景下,用戶會訪問服務器的 Fallback 地址獲取資源,從而保障頁面可用。
2.2.3 多維發(fā)布
另外,針對剛開發(fā)好的應用,我們可以通過發(fā)布平臺的灰度發(fā)布進行發(fā)放,通過外部灰度的形式,對業(yè)務指標進行驗證,達到標準后,方可正式發(fā)布,做到可灰度,可回滾。
更優(yōu)越的 Hybrid 方案:小程序差異化解析
作為超級 App,一個最主要的特征就是開放。開放就是共享 App 的流量,讓外部伙伴的業(yè)務可以通過支付寶觸達用戶,這就面臨一個質量管控的問題。支付寶需要保證這些業(yè)務是合法合規(guī)的,保障用戶的財產安全。
3.1 離線包 VS 小程序
如果開發(fā)一方業(yè)務,離線包肯定是非常好的選擇。不過,要是開放給第三方合作伙伴構建生態(tài)的話,純 HTML5 頁面就有一些劣勢。
上圖是 HTML5 離線包和小程序的細節(jié)對比??偨Y來說,對于開放給第三方的生態(tài),從應用體驗來講,小程序更加統(tǒng)一,質量有保障;從應用安全角度來講,小程序是訪問我方發(fā)布服務器,不會直接訪問第三方鏈接,安全可控;從研發(fā)門檻上來說,小程序是更簡單的前端開發(fā)方式,同時也提供了非常豐富的組件。
3.2 小程序解析
小程序其實和離線包本質是類似的,都是一種 Hybrid 應用,但小程序是基于一個定制的 DSL 語言,不是前端的標準,但是類似。在 DSL 規(guī)則下業(yè)務進行小程序的開發(fā),不支持直接操作 DOM,這種 DSL 規(guī)則下的自由可以有效的進行質量管控。
小程序作為一個應用,他擁有完整的生命周期。從開發(fā)到關閉,開發(fā)者都可以感受到,這點也是 HTML5 所不具備的。另外,每個小程序之間從運行時和持久化上,都是完全隔離的,而且小程序運行在特定進程中,所以和支付寶也是隔離開的。
在渲染性能上,小程序采用雙線程模式將頁面渲染和業(yè)務邏輯分別放在兩個單獨的線程中,renderer 運行在 WebView 中,負責渲染界面;小程序業(yè)務邏輯運行在單獨的 worker 線程,負責事件處理、API 調用和生命周期管理。兩個線程之間通過 postMessage 以及 onMessage 進行數(shù)據(jù)交換,數(shù)據(jù)可以從 worker 線程傳遞到 render 重新渲染界面,同時 renderer 也可以將事件傳遞給對應的 worker 處理。一個 worker 可以對應多個 renderer,方便頁面間數(shù)據(jù)共享和交互。
在資源加載方面,小程序采用離線化方式加載,也就是說當打開小程序時,小程序離線包必須下載到本地,由于每個版本只下載一次,一方面節(jié)省了每次請求的資源開銷,另一方面啟動速度大大提升了。當有新的版本時,發(fā)布平臺自動比對本地安裝的版本和最新版本產生并下發(fā)差量包,客戶端不需要下載整個包即可更新小程序至最新版。
3.3 構建生態(tài)
通過引入相同的小程序架構,使得小程序,可以作為生態(tài)進行多端互投。在支付寶中投放的小程序,可以只經過一些開放接口的適配,即可跑在基于相同小程序架構的 App 中。未來,開發(fā)者或第三方服務更多是面向小程序來開發(fā),而 App 則是提供一個統(tǒng)一的架構,真正做到開放生態(tài),用完即走的理念。
關于支付寶自研 HTML5 容器方案
mPaaS 離線包源自于支付寶原生方案,經歷了嚴苛的業(yè)務考驗,讓你直接和支付寶使用同一套框架層代碼,擁有統(tǒng)一容器及內核,相對系統(tǒng)內核獲取更低 Crash 率和 ANR 率,適配性強,并具備良好的、彈性的擴展能力,結合具體業(yè)務需求定制 JSAPI。
它可以幫助減少 App 白屏、解決 Hybrid App 跨平臺兼容與適配,提升 App 性能并大幅優(yōu)化原生開發(fā)下的包大小。
目前 mPaaS 離線包 Demo 源碼已更新在 GitHub 上,歡迎 Star:
https://github.com/alipay/mpaas-demo
探索 Android 內存優(yōu)化方法
船長的 2019 ,年報元年
全新的視圖綁定工具 — ViewBinding 使用指南
(正文已結束)
推薦閱讀:松下zs70
免責聲明及提醒:此文內容為本網(wǎng)所轉載企業(yè)宣傳資訊,該相關信息僅為宣傳及傳遞更多信息之目的,不代表本網(wǎng)站觀點,文章真實性請瀏覽者慎重核實!任何投資加盟均有風險,提醒廣大民眾投資需謹慎!