JSBridge 技術原理分析

JSBridge 的起源

PhoneGap(Codova 的前身)作爲 Hybrid 鼻祖框架,是一個開源的移動開發框架,允許你用標準的 web 技術 - HTML5,CSS3 和 JavaScript 做跨平臺的 Hybird WebUI 開發,應該是最先被開發者廣泛認知的 JSBridge 的應用場景。而對於 JSBridge 的應用在國內真正興盛起來,則是因爲殺手級應用微信的出現。

JSBridge 是一種 JS 實現的 Bridge,連接着橋兩端的 Native 和 H5。簡單來講,它在 APP 內方便地讓 Native 調用 JS,JS 調用 Native ,是雙向通信的通道。JSBridge 主要提供了 JS 調用 Native 代碼的能力,實現原生功能如查看本地相冊、打開攝像頭、指紋支付等。

既然是『簡單來講』,那麼 JSBridge 的用途肯定不只『調用 Native 功能』這麼簡單寬泛。實際上,JSBridge 就像其名稱中的『Bridge』的意義一樣,是 Native 和非 Native 之間的橋樑,它的核心是 構建 Native 和非 Native 間消息通信的通道,而且是雙向通信的通道。

微信、頭條等小程序基於 Web UI,但是爲了追求運行效率,對 UI 展現邏輯和業務邏輯的 JavaScript 進行了隔離。

JSBridge 的實現原理

JavaScript 是運行在一個單獨的 JS Context 中(例如,WebView 的 Webkit 引擎、JSCore)。由於這些 Context 與原生運行環境的天然隔離,我們可以將這種情況與 RPC(Remote Procedure Call,遠程過程調用)通信進行類比,將 Native 與 JavaScript 的每次互相調用看做一次 RPC 調用。

在 JSBridge 的設計中,可以把前端看做 RPC 的客戶端,把 Native 端看做 RPC 的服務器端,從而 JSBridge 要實現的主要邏輯就出現了:通信調用(Native 與 JS 通信) 和 句柄解析調用。(如果你是個前端,而且並不熟悉 RPC 的話,你也可以把這個流程類比成 JSONP 的流程)

通過以上的分析,可以清楚地知曉 JSBridge 主要的功能和職責,接下來就以 Hybrid 方案 爲案例從這幾點來剖析 JSBridge 的實現原理。

JS 調用 Native

Hybrid 方案是基於 WebView 的,JavaScript 執行在 WebView 的 Webkit 引擎中。因此,Hybrid 方案中 JSBridge 的通信原理會具有一些 Web 特性。

方式 1:注入 API

對於 iOS 來說,

對於 Andriod 來說,

方式 2:攔截 URL SCHEME

URL SCHEME是一種類似於 url 的鏈接,是爲了方便 app 直接互相調用設計的,形式和普通的 url 近似,主要區別是 protocol 和 host 一般是自定義的,例如: qunarhy://hy/url?url=ymfe.tech,protocol 是 qunarhy,host 則是 hy。

攔截 URL SCHEME 的主要流程是:Web 端通過某種方式(例如 iframe.src)發送 URL Scheme 請求,之後 Native 攔截到請求並根據 URL SCHEME(包括所帶的參數)進行相關操作。

在實踐過程中,這種方式有一定的缺陷:

  1. 使用 iframe.src 發送 URL SCHEME 會有 url 長度的隱患。

  2. 創建請求,需要一定的耗時,比注入 API 的方式調用同樣的功能,耗時會較長。

但是這種方式的最重要優勢是跨平臺兼容性,尤其是支持 iOS6,但考慮到終端覆蓋率,已經不是主流方式。

方式 3:重寫 prompt 等原生 JS 方法

WebView 有一個方法,叫setWebChromeClient,可以設置WebChromeClient對象,而這個對象中有三個方法,分別是onJsAlert,onJsConfirm,onJsPrompt,當 js 調用 window 對象的對應的方法,即window.alertwindow.confirmwindow.prompt,WebChromeClient 對象中的三個方法對應的就會被觸發,我們是不是可以利用這個機制,自己做一些處理呢?答案是肯定的。

由於攔截上述方法會對性能造成一定影響,因此需要選擇使用頻率較低的方法,而在 Android 中,相比其它幾個方法,幾乎不會使用到prompt方法,因此佔用prompt是最佳方案。

Native 調用 JS

Native 調用 JS 比較簡單,只要 H5 將 JS 方法暴露在 Window 上給 Native 調用即可。

Android 中主要有兩種方式實現。

JSBridge 如何引用

對於 JSBridge 的引用,常用有兩種方式,各有利弊。

方式 1:由 Native 端進行注入

注入方式和 Native 調用 JavaScript 類似,直接執行橋的全部代碼。

它的優點在於:橋的版本很容易與 Native 保持一致,Native 端不用對不同版本的 JSBridge 進行兼容;

它的缺點是:注入時機不確定,需要實現注入失敗後重試的機制,保證注入的成功率,同時 JavaScript 端在調用接口時,需要優先判斷 JSBridge 是否已經注入成功。

方式 2:由 JavaScript 端引用

與由 Native 端注入正好相反,它的優點在於:JavaScript 端可以確定 JSBridge 的存在,直接調用即可;

缺點是:如果橋的實現方式有更改,JSBridge 需要兼容多版本的 Native Bridge 或者 Native Bridge 兼容多版本的 JSBridge。

參考文獻

作者:alex

來源:https://blog.caogo.cn/2021/02/12/JSBridge%E6%8A%80%E6%9C%AF%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/zkB_9CqYfe5SA47PHcUO0w