iOS離線包加載分享

一餐曹、需求背景

為了提高用戶體驗,針對 APP 內(nèi)嵌的 H5 頁面,有一種比較常見且有效的方式就是接入離線包坪仇,通過把頁面加載需要的靜態(tài)資源提前下載到客戶端本地,避免頁面加載時靜態(tài)資源網(wǎng)絡(luò)請求的開銷垃你,從而來提高頁面的加載速度椅文。

二喂很、知識儲備

1.webview加載h5的過程:

打開一個h5頁面通常會有較長時間出現(xiàn)白屏,以及幾秒后出現(xiàn)內(nèi)容,在這幾秒中到底做了什么事情?因為在這其中做了很多事情,大約包括:

初始化 webview -> 請求頁面 -> 下載數(shù)據(jù) -> 解析HTML -> 請求 js/css 資源 -> dom 渲染 -> 解析 JS 執(zhí)行 -> JS 請求數(shù)據(jù) -> 解析渲染 -> 下載渲染圖片


企業(yè)微信截圖_356e5c7f-df4a-4e61-a5f4-3839285ea6fa.png

一般來說, Webview渲染需要經(jīng)過下面的幾個步驟:

  1. 解析HTML文件
  2. 加載 JavaScript 和 CSS 文件
  3. 解析并執(zhí)行 JavaScript
  4. 構(gòu)建 DOM 結(jié)構(gòu)
  5. 加載圖片等資源
  6. 頁面加載完畢

一般頁面是在dom渲染后才能展示,h5首屏渲染白屏問題的原因關(guān)鍵在于,如何去優(yōu)化請求下載->渲染之間的耗時成了重點.

2.WKWebView攔截請求:

研究了業(yè)內(nèi)已有的 WKWebView 請求攔截方案,主要分為如下兩種:

NSURLProtocol

NSURLProtocol是一個抽象類皆刺,作為URL Loading System系統(tǒng)的一部分少辣,能夠幫助我們攔截所有的URL Loading System的請求,在此進行各種自定義的操作羡蛾,是網(wǎng)絡(luò)層實現(xiàn)AOP(面向切面編程)的利器漓帅。

WKURLSchemeHandler

WKURLSchemeHandler 是 iOS 11 引入的新特性,負責自定義請求的數(shù)據(jù)管理痴怨,如果需要支持 scheme 為 http 或 https請求的數(shù)據(jù)管理則需要 hook WKWebViewhandlesURLScheme: 方法忙干,然后返回NO即可。

兩種方案對比

| NSURLProtocol | WKURLSchemeHandler |
| 隔離性 | 一經(jīng)注冊就是全局開啟浪藻。使用了 NSURLProtocol 的方式后會導(dǎo)致應(yīng)用內(nèi)合作的三方頁面也會被攔截從而被污染捐迫。 | 可以以頁面為維度進行隔離,可以通過WKWebViewConfiguration 進行配置爱葵。 |
| 穩(wěn)定性 | NSURLProtocol 攔截過程中會丟失 Body | WKURLSchemeHandler 在 iOS 11.3 之前 (不包含) 也會丟失 Body施戴,在 iOS 11.3 以后 WebKit 做了優(yōu)化只會丟失 Blob(二進制的一種數(shù)據(jù)類型) 類型數(shù)據(jù) |
| 一致性 | WKWebView 發(fā)出的請求被 NSURLProtocol 攔截后行為可能發(fā)生改變,比如想取消 video 標簽的視頻加載一般都是將資源地址 (src) 設(shè)置為空萌丈,但此時 stopLoading 方法卻不會調(diào)用 | 表現(xiàn)正常 |

****結(jié)論:****WKURLSchemeHandler在隔離性赞哗、穩(wěn)定性、一致性上表現(xiàn)優(yōu)于NSURLProtocol辆雾,但是想在生產(chǎn)環(huán)境投入使用必須要解決 Body 丟失的問題懈玻。

三、技術(shù)實現(xiàn)

H5離線包的基本原理是將html乾颁、js涂乌、css、圖片等靜態(tài)資源打包成壓縮包英岭,然后下載到客戶端并解壓湾盒,H5加載時直接從本地讀取靜態(tài)資源文件,減少網(wǎng)絡(luò)請求诅妹,提高速度罚勾。

3.1 總體流程

222.png

客戶端啟動后,先去遠程配置服務(wù)器拉取離線包相關(guān)的功能配置吭狡,然后檢查更新尖殃,如果有更新則下載離線包。webview加載時划煮,如果本地緩存命中送丰,則從本地磁盤加載html、js弛秋、css器躏、圖片等靜態(tài)資源俐载。。

3.2 離線包和非離線包對比

webView最簡單的做法是直接通過URL去加載一個線上頁面登失。當從瀏覽器輸入一個URL到頁面中間經(jīng)歷了什么?

3333.png

從上面看出用戶加載一個web頁面都要經(jīng)過多次網(wǎng)絡(luò)加載遏佣,中間是極易受到網(wǎng)絡(luò)波動的影響,在無法保證頁面加載的時長和成功率的情況下揽浙,會很大影響用戶體驗状婶。

于是把html、js馅巷、css都抽離出來做成離線包放在本地太抓,這樣加載一個web頁面的過程就如下圖

4444.png

3.3 行業(yè)方案

| 方案名 | 優(yōu)點 | 缺點 | 備注 |
| 加載本地路徑 | 簡單可靠,無需hook和調(diào)用私有API | 有跨域問題令杈,影響cookie和localstorage走敌,H5需做少量改動 | 貨拉拉方案 |
| 請求攔截 | 不修改加載URL,沒有跨域問題逗噩,且支持網(wǎng)頁部分資源離線化掉丽,靈活性和兼容性好 | iOS端目前提供的NSURLProtocol和WKSURLSchemehandler攔截方案有缺陷,前期實現(xiàn)成本高 | 網(wǎng)易云音樂方案zhuanlan.zhihu.com/p/347592487 |
| 本地Web Server | 兼容性好 | 對客戶端耗電和CPU性能有影響 | 暫未發(fā)現(xiàn)有公司采用异雁,juejin.cn/entry/68449… |
| Service Worker | 前端兼容性好 | iOS端WKWebView不提供官方支持捶障,實現(xiàn)技術(shù)難度大 | 愛奇藝方案zhuanlan.zhihu.com/p/148931732 |

四、接入工作:

目前我們采用的方案是:本地文件路徑(file://協(xié)議)纲刀,可能存在一些問題项炼,所以在接入離線包前,我們需要對 H5 項目進行改造示绊。

4.1 問題和解決辦法

| 存在問題 | 解決方法 |
| cgi 請求跨域問題 | 在網(wǎng)關(guān)或者后端服務(wù)的跨域請求頭增加 null 域支持 |
| cookie 跨域問題 | 我們接入的項目中無 cookie 操作锭部,如果有的話,需要改成用請求 header 的方式面褐。 |
| localStorage 跨域問題 | 我們接入的項目中 localStorage 不涉及域名隔離問題拌禾,如果有需要,可以采取調(diào)用原生的方式來做前端存儲展哭。 |
| 資源引用的絕對路徑在離線包模式下不支持 | 改成相對路徑 |

4.2 接口跨域處理

目前我們線上模式的請求鏈路大致為H5 → 網(wǎng)關(guān) → 后臺服務(wù)湃窍,大部分的項目都是通過一級通用網(wǎng)關(guān)來處理跨域問題,但是由于離線包模式下需要網(wǎng)關(guān)設(shè)置允許 origin: null 的場景跨域匪傍,直接在通用網(wǎng)關(guān)處理可能存在安全問題您市。

目前我們的實現(xiàn)如下:

通過hook header["是否是接口請求"]判斷是否攔截請求,然后替換根據(jù)header["x-request-host"]來替換當前的host役衡;一句戶就是app幫助h5請求網(wǎng)絡(luò)再把結(jié)果回調(diào)給h5茵休。

五、參考資料

蘋果官方文檔https://developer.apple.com/documentation/webkit/wkwebview?language=objc

貨拉拉H5接入離線包的實踐總結(jié) zhuanlan.zhihu.com/p/538288299

WKWebView之離線加載以及遇到的問題https://blog.csdn.net/Lu_Ca/article/details/125723040

WKWebview秒開實踐分享及問題解決方案(抖音)https://juejin.cn/post/6887161842406260744#heading-6

WKWebView 請求攔截探索與實踐(網(wǎng)易)https://juejin.cn/post/6922625242796032007

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市泽篮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柑船,老刑警劉巖帽撑,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鞍时,居然都是意外死亡亏拉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門逆巍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來及塘,“玉大人,你說我怎么就攤上這事锐极◇狭牛” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵灵再,是天一觀的道長肋层。 經(jīng)常有香客問我,道長翎迁,這世上最難降的妖魔是什么栋猖? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮汪榔,結(jié)果婚禮上蒲拉,老公的妹妹穿的比我還像新娘。我一直安慰自己痴腌,他們只是感情好雌团,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著士聪,像睡著了一般辱姨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上戚嗅,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天雨涛,我揣著相機與錄音,去河邊找鬼懦胞。 笑死替久,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的躏尉。 我是一名探鬼主播蚯根,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了颅拦?” 一聲冷哼從身側(cè)響起蒂誉,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎距帅,沒想到半個月后右锨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡碌秸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年绍移,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讥电。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡蹂窖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出恩敌,到底是詐尸還是另有隱情瞬测,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布纠炮,位于F島的核電站涣楷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏抗碰。R本人自食惡果不足惜狮斗,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望弧蝇。 院中可真熱鬧碳褒,春花似錦、人聲如沸看疗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽两芳。三九已至摔寨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間怖辆,已是汗流浹背是复。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留竖螃,地道東北人淑廊。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像特咆,于是被迫代替她去往敵國和親季惩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容