1.背景
H5 頁(yè)面做秒開優(yōu)化是業(yè)務(wù)的常規(guī)操作,一般正常通過(guò)網(wǎng)絡(luò)請(qǐng)求的 H5 頁(yè)面,我們都是圍繞資源加載速度優(yōu)化展開。優(yōu)化手段主要分兩個(gè)方向,一個(gè)是提升網(wǎng)絡(luò)速度,一個(gè)是減少資源大小。
提升網(wǎng)絡(luò)速度,一般的手段有 DNS 預(yù)解析、多域名、升級(jí) HTTP2、使用 CDN、SSR。而即使有靜態(tài)資源的網(wǎng)絡(luò)緩存,HTML 也只能用協(xié)商緩存,需要消耗一次網(wǎng)絡(luò)請(qǐng)求。這也注定了無(wú)法避免因網(wǎng)絡(luò)問(wèn)題導(dǎo)致的頁(yè)面白屏?xí)r間較長(zhǎng)的問(wèn)題,在我們真實(shí)的數(shù)據(jù)中也能得到印證,無(wú)論怎么優(yōu)化,頁(yè)面的 1.5 秒開穩(wěn)定在 90% 以上非常困難。
因此,如果想實(shí)現(xiàn) 95% 以上甚至 99% 以上秒開,離線化 H5 是必然的選擇。同時(shí)根據(jù)歷史經(jīng)驗(yàn),隨著 iOS 和 Android 手機(jī)的性能不斷提升,Webview 的渲染性能也不斷提升,目前大部分手機(jī)的 H5 離線化渲染都可以實(shí)現(xiàn)無(wú)白屏體驗(yàn),無(wú)限接近原生的交互體驗(yàn)。
?文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-710385.html
2.收益
在實(shí)踐過(guò)程中,我們分兩個(gè)場(chǎng)景構(gòu)建離線化 H5 基座,一個(gè)是由 H5 開發(fā)的新 APP,一個(gè)是汽車之家 APP。
主機(jī)廠內(nèi)部有一個(gè)應(yīng)用,第一版是 Native 和 H5 的混合開發(fā),會(huì)通過(guò)網(wǎng)絡(luò)請(qǐng)求資源,雖然有網(wǎng)絡(luò)緩存,但是第一次打開也很慢,非常影響用戶體驗(yàn),內(nèi)部性能監(jiān)控平臺(tái)顯示首屏平均耗時(shí) 1s。后面全面改造成內(nèi)置離線 H5 應(yīng)用,Native 只提供橋功能,首屏平均耗時(shí)減少到 237ms,加載速度提升 4 倍,大部分情況下實(shí)現(xiàn)無(wú)白屏體驗(yàn)。業(yè)內(nèi)曾經(jīng)做過(guò)人眼識(shí)別白屏的最小時(shí)間測(cè)試,當(dāng)降到 200ms 左右時(shí),人眼幾乎無(wú)法識(shí)別白屏。
新 APP 我們主要使用 H5 開發(fā),而不是用 Flutter 或者 RN 等技術(shù),最主要的原因是人才儲(chǔ)備不足,在業(yè)務(wù)場(chǎng)景并沒(méi)有特別復(fù)雜的原生體驗(yàn)情況下,我們發(fā)現(xiàn)業(yè)務(wù)迭代,對(duì)客戶端的依賴大大減少,溝通成本降低,迭代效率有明顯提高,團(tuán)隊(duì)不需要面對(duì)復(fù)雜的 Flutter 和 RN 引擎,也不需要熟悉客戶端的開發(fā)模式。
汽車之家 APP 中,由于歷史原因,不能預(yù)置離線包 H5,所以只能有選擇性地進(jìn)行動(dòng)態(tài)預(yù)加載,而這會(huì)導(dǎo)致在開屏等特殊場(chǎng)景下,訪問(wèn)速度仍然不高。整體上首屏?xí)r間從 1240.4ms 縮短為 505.4ms,加載速度提升一倍。
?
3.技術(shù)架構(gòu)

?離線化 H5 Hybrid 架構(gòu)上,主要分成四大模塊:H5 離線包管理工具、APP 開發(fā)工具、Native 運(yùn)行時(shí)和 Webview 運(yùn)行時(shí)。
?
4.離線包管理工具
H5 離線包管理工具包含:離線包管理平臺(tái)、之家云打包腳本。離線包管理平臺(tái)包含:APP 應(yīng)用管理、H5 應(yīng)用管理、發(fā)布回滾、開關(guān)控制四大功能。通過(guò)和之家云發(fā)布流水線聯(lián)動(dòng),可以實(shí)現(xiàn)網(wǎng)絡(luò)版和離線版 H5 的版本同步,發(fā)布操作也實(shí)現(xiàn)同步,由于之家云功能限制,回滾目前還不支持聯(lián)動(dòng)。
管理的物料包括:H5 離線包(H5 代碼、離線包配置文件)、APP 離線包配置文件。APP 配置文件,在沒(méi)有預(yù)置離線包的情況下,下載資源是阻塞性的。為了提升下載速度和可用性,APP 配置文件也被維護(hù)成了一個(gè) CDN 上的 JSON 文件。
4.1
離線包發(fā)布流程
在之家云發(fā)布平臺(tái),使用離線包管理 CLI 工具,執(zhí)行上傳離線包命令,并配置一個(gè)離線包發(fā)布的 Webhook,即可實(shí)現(xiàn)自動(dòng)化離線包發(fā)布。離線管理平臺(tái)會(huì)同步之家云平臺(tái)的離線包版本號(hào)。

4.2
離線包設(shè)計(jì)
和普通的 H5 打包文件相比,離線包新增了一個(gè)專屬的離線包配置文件 config.json,同時(shí)會(huì)把資源打包成 gzip 壓縮包,從而提升整體資源的下載速度。
資源目錄
h5id
├──?js/
├──?css/
├──?img/
├──?pages
│???├──?index.html
│???└──?list.html
└──?config.json(配置文件)
配置文件
interface?HybridConfig?{
??//?離線?H5?APP?ID
??h5id:?string;
??//?匹配頁(yè)面和靜態(tài)資源的規(guī)則
??mapping:?{
????[env:?string]:?{
??????pages:?Resource[];
??????resources:?Resource[];
????}
??};
??package:?{
????//?離線包資源目錄路徑,根目錄相對(duì)路徑
????file:?string;
????//?包含的文件,和?excludes?互斥,只能同時(shí)有一個(gè)
????includes:?{
??????ext:?string[];
??????file:?string[];
????};
????//?不包含的文件
????excludes:?{
??????ext:?string[];
??????file:?string[];
????};
????//?Native?APP?版本適配
????appRules:?{
??????//?離線包管理平臺(tái)的應(yīng)用?ID
??????[appid:?string]:?{
????????//?[最小版本,最大版本]
????????ios:?[string,?string];
????????android:?[string,?string];
??????}
????};
??}
}
interface?Resource?{
??//?攔截到的請(qǐng)求 url 的規(guī)則,不提供 http 或者 https,支持單個(gè)文件和文件目錄。
??//?例如:example.com/page,example.com/static/img.png
??remoteUrl:?string;
??//?和 downloadUrl 必須有一個(gè)存在,相對(duì)離線包所在目錄的文件路徑。
??//?「path」值會(huì)替換掉請(qǐng)求 url 中的「remoteUrl」字符串。
??path?:?string;
??//?和?path?必須有一個(gè)存在,指定下載資源的?url,
??//?下載后存放在離線包的 vendor 目錄下。
??//?并把存儲(chǔ) path 同步到配置文件的 path 字段。
??downloadUrl?:?string;
??//?可選的?mime?type,如果不提供,通過(guò)文件名后綴自動(dòng)補(bǔ)償
??contentType?:?string;
}
?
4.3?
打包命令行工具
-
?打包發(fā)布腳本發(fā)布到之家私有源,以腳手架命令形式調(diào)用,提供打包、上傳命令;
-
業(yè)務(wù)方結(jié)合自身編譯上線流程進(jìn)行調(diào)用,上傳完成則自動(dòng)進(jìn)行發(fā)布;
-
?前端靜態(tài)資源按照頁(yè)面/工程緯度打包成zip;
-
zip包含js/css/img/pages/config.json配置文件;
//?腳本安裝
npm?i?@auto/dt-fe-cli
//?編譯上傳
//?指定腳本的配置文件,打包并上傳至服務(wù)器,默認(rèn)配置文件為?config.json,可以使用?--config?指定配置文件
dt-fe-cli?offline?--config?hybrid-config.json
?
4.4?
管理平臺(tái)
為了更好管理離線包,我們提供了一個(gè)簡(jiǎn)潔的管理后臺(tái),用來(lái)管理 H5 應(yīng)用和 APP 應(yīng)用的關(guān)系,記錄之家云編譯好的離線包,同時(shí)提供 APP 配置給客戶端查詢。為了提高 APP 配置下載速度和可靠性,我們用 CDN 上的 JSON 文件來(lái)存儲(chǔ) APP 配置。
?4.4.1?APP 配置
interface?APPConfig?{
??appid:?string;
??version:?string;
??updateTime:?string;
??isIosEnable:?boolean;
??isAndroidEnable:?boolean;
??H5Apps:?H5App[];
}
interface?H5App?{
??//?H5?應(yīng)用的?APP?ID
??h5Id:?string;
??versions:?H5Config[];
??lastVerison:?{};
??latestUrl:?string;
}
interface?H5Config?{
??version:?string;
??//?true,開啟離線化
??isEnable:?boolean;
??//?true,開啟?iOS?APP?離線化
??isIosEnable:?boolean;
??//?true,開啟?Android?APP?離線化
??isAndroidEnable:?boolean;
??//?true,需要預(yù)先加載
??isPreLoad:?boolean;
??pages:?Resource[];
??appRules:?AppRules;
??downloadUrl:?string;
}
interface?Resource?{
??//?攔截到的請(qǐng)求 url 的規(guī)則,支持單個(gè)文件和文件目錄。例如:/page,/static/img.png
??remoteUrl:?string;
??//?和 downloadUrl 必須有一個(gè)存在,相對(duì)離線包所在目錄的文件路徑。
??//?path?會(huì)替換掉請(qǐng)求?URL?中的「remoteUrl」字符串
??path?:?string;
??//?和 path 必須有一個(gè)存在,指定下載下載資源的 url,下載后存放在離線包的 vendor 目錄下。
??//?并把存儲(chǔ) path 同步到配置文件的 path 字段。
??//?下載失敗,則該匹配規(guī)則失效自動(dòng)訪問(wèn)網(wǎng)絡(luò)資源
??downloadUrl?:?string;
??//?可選的?mime?type,如果不提供,通過(guò)文件名后綴自動(dòng)補(bǔ)償
??contentType?:?string;
}
interface?AppRules?{
??//?ios?APP?的開始和結(jié)束版本,最大版本可設(shè)置?infinite
??ios:?[string,string];
??android:?[string,string];
}
?
?4.4.2 管理平臺(tái)截圖



5.客戶端設(shè)計(jì)
作為整體 Hybrid 離線包應(yīng)用架構(gòu)中的重要一環(huán),端內(nèi) Hybrid 離線包 SDK 包括 Webview 管理、離線包管理、Bridge 三個(gè)模塊。

5.1?
Webview管理
-
定制 Hybrid 瀏覽器,設(shè)置可通過(guò)特定 Scheme 協(xié)議打開;
-
如果沒(méi)有離線資源,可以降級(jí) HTTP 請(qǐng)求,也可以選擇阻塞下載;
-
通過(guò) H5 應(yīng)用映射表匹配當(dāng)前頁(yè)面 Url 和緩存資源,存在緩存資源時(shí),Hybrid 瀏覽器攔截 H5 所有資源請(qǐng)求,執(zhí)行本地緩存邏輯:命中緩存時(shí)直接返回本地資源;未命中緩存則交還給WebView進(jìn)行默認(rèn)處理;
-
關(guān)閉 Hybrid 瀏覽器時(shí)觸發(fā)離線包管理邏輯,進(jìn)行資源更新。
5.2?
離線包管理
-
?APP 預(yù)置:APP 打包時(shí)可以使用命令行工具批量下載需要預(yù)置的離線包,并集成到 APP 中;
-
預(yù)加載:有時(shí)候出于 APP 體積的考慮,我們不能預(yù)置所有離線包,為了提高離線包的加載體驗(yàn),可以開啟預(yù)加載,在 APP 啟動(dòng)后的空閑時(shí)間主動(dòng)進(jìn)行離線包下載;
-
更新:根據(jù)唯一性原則,同一個(gè) H5 應(yīng)用同時(shí)只保留一份離線資源;
-
磁盤空間管理:及時(shí)刪除下載失敗或已解壓完成的 ZIP 包;清理舊版本離線資源;結(jié)合 LRU 算法進(jìn)行離線包緩存上限管理。
-
環(huán)境隔離
5.3?
環(huán)境區(qū)分及降級(jí)處理
-
H5 應(yīng)用區(qū)分測(cè)試、生產(chǎn)環(huán)境,不同環(huán)境匹配不同離線資源;
-
通過(guò)預(yù)支的字段開關(guān)可以控制是否啟用離線包邏輯,開關(guān)關(guān)閉時(shí)直接使用線上資源。
5.4?
Hybrid 離線包方案的下一步規(guī)劃
Hybrid 方案在預(yù)加載模式下取得了較好的效果,有效的提升了 H5 頁(yè)面的秒開率,后續(xù)將在以下幾個(gè)方面繼續(xù)提升 Hybrid 方案的能力,更好的為主機(jī)廠相關(guān)業(yè)務(wù)助力。
-
增加并完善預(yù)置離線包能力:在 APP 大小可控的前提下,在 APP 內(nèi)預(yù)置關(guān)鍵頁(yè)面的離線包,彌補(bǔ)預(yù)加載邏輯在第一次打開時(shí)命中率低的不足。APP接入預(yù)置離線包后,頁(yè)面第一次打開時(shí)預(yù)計(jì)資源命中率提高到100%。完成相關(guān)方案如下:

-
增加 One Shot 能力(類小程序):支持在 Hybrid 瀏覽器首次訪問(wèn) H5 應(yīng)用時(shí),實(shí)時(shí)下載離線資源包并匹配離線資源。APP接入One Shot 能力后,頁(yè)面第二次打開時(shí)預(yù)計(jì)資源命中率提高到100%。相關(guān)方案如下:

6.踩過(guò)的坑
6.1?
Post 請(qǐng)求丟失 Body
?iOS 系統(tǒng),瀏覽器攔截協(xié)議有 NSURLProtocol 和 WKURLSchemeHandler 兩種,并且都存在 Post 請(qǐng)求丟失 Body 的問(wèn)題,針對(duì) Post 請(qǐng)求都需專門處理。
開始時(shí)使用的是 NSURLProtocol 協(xié)議,優(yōu)點(diǎn)是可挑選處理請(qǐng)求,不需要處理的可拋回瀏覽器,但是在特殊場(chǎng)景下出現(xiàn)問(wèn)題:NSURLProtocol 是全局?jǐn)r截,打開后所有瀏覽器都會(huì)進(jìn)行攔截,所以在多個(gè)瀏覽器同時(shí)存在,并且非Hybrid瀏覽器還有發(fā)送 Post 請(qǐng)求時(shí),Post 請(qǐng)求 Body 會(huì)丟失,導(dǎo)致請(qǐng)求失敗。NSURLProtocol 的全局?jǐn)r截問(wèn)題無(wú)法解決,于是又將目光移向 WKURLSchemeHandler,開始了完全自己實(shí)現(xiàn)Http請(qǐng)求。
6.2?
無(wú)侵入式攔截
?WKURLSchemeHandler 需要解決的問(wèn)題有很多,包括Cookies,重定向,Post請(qǐng)求支持等。最開始沿用了NSURLProtocol Post 請(qǐng)求處理方法,業(yè)務(wù)方將Post請(qǐng)求通過(guò)橋的方式,扔給Native進(jìn)行請(qǐng)求,但緊接著就遇到另一個(gè)問(wèn)題:需要業(yè)務(wù)方配合改造。作為一個(gè)通用平臺(tái),接入成本過(guò)高是一個(gè)致命問(wèn)題,直接影響業(yè)務(wù)方接入的意愿。
實(shí)現(xiàn)無(wú)侵入式攔截,是我們必須要解決的問(wèn)題,最終通過(guò)多次實(shí)驗(yàn),采用了JS注入攔截的方式,具體流程主要為以下幾點(diǎn):
-
若命中離線,加載網(wǎng)頁(yè)時(shí)開啟Handler攔截,注入 Fetch /? XMLHttpRequest 攔截請(qǐng)求腳本;
-
發(fā)送請(qǐng)求時(shí),Post請(qǐng)求通過(guò)Bridge發(fā)送給Native,Get請(qǐng)求又傳遞給原生應(yīng)用進(jìn)行存儲(chǔ)處理WKURLSchemeHandler;
-
Handler攔截的請(qǐng)求若命中離線,走本地資源匹配,匹配到后模擬請(qǐng)求返回H5,未命中時(shí)Native發(fā)送請(qǐng)求;
-
Post請(qǐng)求,Native通過(guò)橋拿到url和Body信息,通過(guò)原生請(qǐng)求發(fā)送,結(jié)果透?jìng)鹘oH5。

?
7.總結(jié)
隨著移動(dòng)設(shè)備整體性能的持續(xù)提升,離線化 H5 Hybrid技術(shù)架構(gòu)在加載和交互體驗(yàn)方面取得了顯著改善。在許多標(biāo)準(zhǔn)應(yīng)用場(chǎng)景中,它能夠提供接近原生應(yīng)用的用戶體驗(yàn)。此外,它的跨平臺(tái)、低成本、充足的人才資源、豐富的生態(tài)系統(tǒng)和動(dòng)態(tài)更新等優(yōu)勢(shì),使其在與其他跨平臺(tái)解決方案的比較中脫穎而出。
?
作者|?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-710385.html
到了這里,關(guān)于汽車之家主機(jī)廠離線化 H5 Hybrid 實(shí)踐的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!