如何打造移動端Hybrid框架

一、前言

移動端動態(tài)化方案之多,令人嘆為觀止

移動端動態(tài)化分類

1)Web容器增強,這是我們今天討論的重點,核心就是基于Chromium和WebKit的能力做訂制增強版,代表作Cordova,VasSonic等

2)虛擬運行環(huán)境,自建一套虛擬環(huán)境,要么使用原生能力渲染,要么自己獨立渲染,代表作RN,F(xiàn)lutter等

3)布局動態(tài)化,這是偏Natvie動態(tài)化的方式,一般采用布局引擎+JSON的實現(xiàn)方式,簡單高效,布局引擎代表作Yoga,F(xiàn)lexboxLayout等

4)Native動態(tài)化,Native的動態(tài)化一直是被人所詬病的,熱修復(fù)就是解決這一問題最好的方式,有人會在Natvie動態(tài)化分類里包含插件化,但個人認(rèn)為一來插件化的技術(shù)已經(jīng)是過去式,二來插件化主要還是在Android上的應(yīng)用

接下來我們展開聊一聊Web容器增強這一分類

二、背景

Web增強容器技術(shù)方案本身并不復(fù)雜,但如果想把它做好還需要做很多加持技術(shù)的實現(xiàn),接下來我們來討論下這兩類技術(shù)的實現(xiàn)

三、Web容器增強本身技術(shù)實現(xiàn)

【1】JS到Native的通信實現(xiàn)

1)iOS實現(xiàn),利用WKUserContentController的addScriptMessageHandler方法給messageHandlers注入對象,在JS層使用window.webkit.messageHandlers.注入的對象.postMessage()來觸發(fā)調(diào)用,接收到指定對象后,解析出指定類和指定方法,利用OC的Runtime動態(tài)調(diào)用指定類的指定方法

2)Android有兩種實現(xiàn),一種利用WebView的addJavascriptInterface方法給全局window對象注入對象(Java類中使用@JavascriptInterface標(biāo)注的方法均可以訪問),在JS層直接調(diào)用暴露出的方法;一種方法是利用JS的prompt機制,在WebChromeClient的onJsPrompt進(jìn)行通信處理,Android4.1(JellyBean)之前如果addJavascriptInterface被禁用掉,就只能使用這種方案,這種方案可以保證在所有Android平臺上都可以進(jìn)行JS到Native的通信

雙端傳遞的數(shù)據(jù)是一致的,為一個數(shù)組[callbackId, service, action, actionArgs],callbackId為這次調(diào)用的回調(diào)ID,在JS層可以通過這個回調(diào)ID查詢到成功回調(diào)和失敗回調(diào),service為類名,action為方法名,actionArgs為方法的參數(shù)

【2】Native到JS的通信實現(xiàn)

1)iOS實現(xiàn),利用WKWebView的evaluateJavaScript:completionHandler:方法執(zhí)行JS層暴露出來的回調(diào)Function

2)Android實現(xiàn),利用WebView的evaluateJavascript方法執(zhí)行JS層暴露出來的回調(diào)Function

這里需要注意,維系前端和客戶端callback關(guān)系的是callbackID,成功和失敗的callback Function會存儲在JS層,前端調(diào)到客戶端的時候會將callbackID傳遞過來,客戶端調(diào)回前端再將callbackID傳遞回去,前端拿到callbackID,再找到成功和失敗的callback Function,并且執(zhí)行

【3】容器增強插件機制實現(xiàn)

對于Web容器的增強,端能力是至關(guān)重要的一環(huán),我們在業(yè)務(wù)開發(fā)中會寫很多不同種類的端能力,所以將端能力做成插件機制是比較方便的選擇,一般的實現(xiàn)思路就是定義一個Plugin的基類,在里邊定義初始化,執(zhí)行,重置,銷毀等鉤子函數(shù),以及一些系統(tǒng)的生命周期函數(shù),比如iOS的onAppTerminate和onMemoryWarning等,比如Android的onStart,onStop,onNewIntent,onDestroy等

四、Web容器增強加持技術(shù)實現(xiàn)

【1】預(yù)下載實現(xiàn)

Web容器加載的巨大瓶頸在線上資源,所以將資源本地化是解決這一問題的利器

Web容器包管理

為了讓下載成功率更高,除了上圖的方案和策略外,還可以對資源包進(jìn)行增量更新,讓需要下載的資源包更小,從而達(dá)到提升下載成功率的目的

【2】預(yù)創(chuàng)建實現(xiàn)

WebView的提前創(chuàng)建會節(jié)省一部分時間,更極致的做法是提前創(chuàng)建WebView復(fù)用池,要針對不同的策略來選擇,比如線上的加載走一套,線下的加載走一套

【3】預(yù)渲染實現(xiàn)

1)客戶端預(yù)渲染實現(xiàn),一般的H5頁面都會分為骨架和內(nèi)容,預(yù)渲染主要旨在預(yù)渲染骨架部分,骨架部分一般是渲染一次,后邊會一直使用,也可以預(yù)渲染內(nèi)容,這種方案叫CSR(Client Side Rendering)

2)服務(wù)端預(yù)渲染,服務(wù)端直接把骨架和內(nèi)容進(jìn)行渲染,直接返回給客戶端渲染好的HTML,這種方案叫SSR(Server Side Rendering),但這也會增加服務(wù)端的計算資源,從而造成成本的增加

從SSR到CSR的5種技術(shù)形態(tài)

上圖是從SSR到CSR的5種不同技術(shù)形態(tài),其中站在客戶端角度使用頻次最高的是CSR with Prerendering

【4】網(wǎng)絡(luò)接管機制實現(xiàn)

對于Web容器的加載,Android上由于系統(tǒng)WebView兼容性較差,都會基于chromium自建瀏覽內(nèi)核,或者使用第三方瀏覽內(nèi)核,比如騰訊的X5內(nèi)核;在iOS上使用WKWebView

Web容器的加載核心在網(wǎng)絡(luò)請求和渲染數(shù)據(jù)上,如果是自建瀏覽內(nèi)核的話,這兩點都能做到白盒化,但絕大部分團(tuán)隊是沒有這個能力的,所以可以退而求其次進(jìn)行網(wǎng)絡(luò)請求的接管,但做網(wǎng)絡(luò)請求的接管是要建立在對網(wǎng)絡(luò)的精細(xì)優(yōu)化上的,不然這種技術(shù)方案的成效會大打折扣,接下來讓我們看下具體接管實現(xiàn)方案

1)Android上的網(wǎng)絡(luò)接管機制實現(xiàn)

核心關(guān)鍵是WebViewClient的shouldInterceptRequest方法,通過攔截這個方法可以將一個Request對象轉(zhuǎn)成一個Response對象

這里需要注意兩點,一是重定向的請求攔截不到,這個需要看業(yè)務(wù)需求;二是shouldInterceptRequest跑在子線程,所以可以使用同步的網(wǎng)絡(luò)請求方式獲取數(shù)據(jù),HttpURLConnection是最佳選擇,一般會使用URLStreamHandlerFactory進(jìn)行底層網(wǎng)絡(luò)的接管,達(dá)到極致優(yōu)化的目的

2)iOS上的網(wǎng)絡(luò)接管機制實現(xiàn)

核心關(guān)鍵是利用URL Loading System機制,使用URLProtocol的registerClass注冊全局的自定義Protocol對象(建議注冊一個Protocol,注冊多個Protocol會造成不必要的沖突問題)

在iOS11以上,使用WKURLSchemeHandler來接管http和https的請求,但會拋出"https is a URL scheme that WKWebView handles natively",經(jīng)查閱webkit源碼,需要使用runtime hook webkit的handlesURLScheme方法,不處理http和https的請求,通過[configuration setURLSchemeHandler:schemeHandler forURLScheme:@"https"]來進(jìn)行接管注冊

五、結(jié)語

移動端Web容器增強技術(shù)是一個古老的技術(shù),很多年依然盛行,個人覺著有2點

1)前端陣營的繁榮

2)在四種動態(tài)化技術(shù)方案里最復(fù)雜,但由于Chromium和Webkit已經(jīng)非常成熟,所以上手成本較低,可以快速落地

六、參考資料

【1】https://github.com/apache/cordova-android

【2】https://github.com/apache/cordova-ios

【3】https://www.infoq.cn/article/rlDGpUSTHQxeUQ4FQJ7T

【4】https://github.com/Tencent/VasSonic

【5】https://github.com/Tencent/VasSonic/blob/master/assets/sonic%E5%8F%91%E5%B1%95%E5%8E%86%E7%A8%8B.md

【6】https://developers.google.cn/web/updates/2019/02/rendering-on-the-web

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容