摘要:上面提到在安卓完全不需要像這樣大費周章的繞彎路,所以安卓可能就不需要這個自定義的,這樣又會導致面臨著與安卓差異化嚴重問題。
前言最早接觸離線包的概念要追溯到16年初,項目迎來大改版,其中重點項目之一就是離線包方案的制定與實施。離線包顧名思義就是將H5/CSS/JS和資源文件打包提前下發(fā)到App中,這樣App在加載網(wǎng)頁的時候?qū)嶋H上加載的是本地的文件,減少網(wǎng)絡請求來提高網(wǎng)頁的渲染速度,并實現(xiàn)動態(tài)更新效果。
就目前情況來看,離線包的方案也是層出不窮的,在文末參考部分,總結(jié)了一些文章入口,如果有這方面的需求的也可以進行參考。
回歸主題,本篇將從iOS現(xiàn)有的四種離線方案進行探討分析,目的在于探索一個最佳方案來實施我們的離線包功能,也希望對你能有所幫助。
目錄1. 構(gòu)建離線包管理平臺
2. 離線包加載方案探究
3. fallback 技術
4. 總結(jié)
一、構(gòu)建離線包管理平臺
1.后端使用離線包管理平臺把同一個業(yè)務模塊相關的頁面和資源打包成一個zip壓縮包文件,同時對文件加密/簽名。
2.客戶端根據(jù)本地數(shù)據(jù)庫表,和服務端進行版本校驗,做增量、全量更新操作,做解壓/解密/校驗等工作。
3.根據(jù)數(shù)據(jù)庫表,打開某個業(yè)務時轉(zhuǎn)接到打開離線包的入口頁面,即我們常見的index.html。
4.攔截網(wǎng)絡請求,對于離線包已經(jīng)有的文件,直接讀取離線包數(shù)據(jù)返回,否則走http協(xié)議緩存邏輯。
對于離線包平臺的構(gòu)建是十分有必要的,建議如果實施離線包方案,那就同步實施離線包平臺構(gòu)建,負責離線包的增刪改功能,當然這就不單單是客戶端的事情了。
本篇著重討論第四步,攔截網(wǎng)絡請求。 二、離線包加載方案探究 方案一:獲取沙盒html路徑直接加載index.html
1.將所有的h5文件都放入一個文件夾中。
2.將這個文件夾以相對路徑的方式倒入到工程代碼中。
3.獲取本地的文件路徑。
這個方案就是將部署在服務器上面的前端代碼直接解壓到本地沙盒。加載js的時候直接加載本地沙盒中的html進行離線加載。將每個前端的模塊都定義為一個應用,打上id下發(fā)給客戶端,當用戶點擊對應模塊的時候根據(jù)id去沙盒查找對應的離線資源進行加載實現(xiàn)秒開。
優(yōu)點:簡單。
缺點:
實際上我們在訪問本地html的時候可以看到實際路徑為file:///.../index.html。這是在使用file協(xié)議訪問html,有些html樣式并不支持file協(xié)議,在樣式和功能上會有缺失,還會有一些api上的差異,前端開發(fā)好的代碼可能部署到沙盒里導致有些資源無法使用,產(chǎn)生一些適配問題。
訪問本地資源可能會導致資源路徑泄漏產(chǎn)生安全問題。
還會有一些瀏覽器的安全設置無法通過。
無法實現(xiàn)跨域資源請求,會讓前端開發(fā)人員無法訪問外部cdn。
file協(xié)議&http協(xié)議:file協(xié)議主要用于訪問本地計算機中的文件,好比通過資源管理器打開文件一樣,針對本地的,即file協(xié)議是訪問你本機的文件資源。http協(xié)議訪問本地html是在本地起了一臺http服務器,然后你訪問自己電腦上的本地服務器,http服務器再去訪問你本機的文件資源。
瀏覽器對兩種協(xié)議的處理有時會不同,譬如某些網(wǎng)頁中直接調(diào)用file協(xié)議來打開圖片,這樣的功能會被瀏覽器的安全設置阻擋,因為默認上,html是運行于客戶端的超文本語言,從安全性上來講,服務端不能對客戶端進行本地操作。即使有一些象cookie這類的本地操作,也是需要進行安全級別設置的。倘若你需要載入外部cdn的資源,比如livereload、browserSync等工具的使用,由于瀏覽器的同源策略,從本地文件系統(tǒng)載入外部文件將會失敗,會拋出安全性異常。
總的來說,這個方案會對前端產(chǎn)生嚴重的入侵,限制了前端只能通過相對路徑對js,css,image等資源的加載,還有file協(xié)議的跨域問題導致無法引入外部cdn,這樣會限制前端開發(fā),雖然用起來最簡單,但這并不是一個好的方案。
方案二:使用protocol攔截既然直接加載本地html不是最好方案,那我們將加載html后的所以資源請求全部攔截,映射為本地資源重新組裝request進行http請求并加載,是否可行呢?當然可行了,但是往下看:
在UIWebView上,protocol攔截確實是我們的首選方案,創(chuàng)建個子類,在子類里面實現(xiàn)protocol的代理方法即可實現(xiàn)對所有請求的攔截,當然也包括html里面對資源加載的請求。
那么在WKWebView上,這個方案是行不通的,關于這方面的解釋已經(jīng)很多了,WKWebView在獨立于app進程之外的進程中執(zhí)行網(wǎng)絡請求,請求數(shù)據(jù)不經(jīng)過主進程,因此,在WKWebView上直接使用 NSURLProtocol 無法攔截請求。當然通過私有api可以解決問題,但依然存在缺陷,post請求body數(shù)據(jù)被清空。由于WKWebView在獨立進程里執(zhí)行網(wǎng)絡請求。一旦注冊http(s) scheme后,網(wǎng)絡請求將從Network Process發(fā)送到App Process,這樣 NSURLProtocol 才能攔截網(wǎng)絡請求。在webkit2的設計里使用MessageQueue進行進程之間的通信,Network Process會將請求encode成一個Message,然后通過 IPC 發(fā)送給 App Process。出于性能的原因,encode的時候HTTPBody和HTTPBodyStream這兩個字段被丟棄掉了。
此段引自:《WKWebView》
關于丟Body的解決方案可以戳上文詳細查看。如果使用Get請求攔截離線資源可以通過設置自定義的customScheme:進行攔截,例如customScheme://.../.css,攔截后加載本地離線資源。但是使用私有api又會面臨另外一個風險:被拒。
說一點題外話,目前據(jù)我所了解到百度App安卓就是采用的請求攔截方式,但是,是安卓,看下圖:
圖片來源《百度APP-Android H5首屏優(yōu)化實踐》
通過上圖可以分析第11、12步,WebView對html解析的時候可以發(fā)現(xiàn)資源請求并攔截,返回對應的緩存資源并渲染。實際上這個方案在iOS上是行不通的,安卓可以使用自家瀏覽器,可以魔改瀏覽器,比如支付寶的UC,百度的T7等。iOS應用內(nèi)是不允許使用魔改瀏覽器的,很遺憾,也就是說蘋果爸爸開放了什么,我們才能使用什么。
總結(jié)來說,這個方案并不會對前端產(chǎn)生入侵,但對于body的攔截和對私有api的使用,產(chǎn)生上架被拒風險,另外protocol是一個全局的攔截,可能也并不是我們想要的,所以這個方案仍然不推薦。
方案三:WKURLSchemeHandlerWKURLSchemeHandler是iOS11就推出的,用于處理自定義請求的方案,不過并不能處理Http、Https等常規(guī)scheme。
WKWebViewConfiguration開放了setURLSchemeHandler:forURLScheme:函數(shù),需要指定一個自定義的scheme和一個用來處理WKURLSchemeHandler回調(diào)的自定義對象。
根據(jù)注釋來看,如果注冊了一個無效的scheme或者使用WebKit內(nèi)部已經(jīng)處理的scheme將會引發(fā)異常。我們最好使用WKWebView的handlesURLScheme:類方法來檢查給定scheme的可用性,以免帶來一些未知問題。
WKURLSchemeHandler提供了兩個回調(diào)函數(shù)由上面自定義的對象來處理:
- (void)webView:(WKWebView *)webView startURLSchemeTask:(id)urlSchemeTask; - (void)webView:(WKWebView *)webView stopURLSchemeTask:(id )urlSchemeTask;
通過urlSchemeTask的request對象可以拿到請求對應的url,如果是我們自定義的scheme就去攔截它,并加載本地資源。
實際上這個方案解決了資源攔截的問題,但是它依然有很多短板:
因為使用的自定義scheme,并不是http協(xié)議,所以它依然無法解決跨域問題。
由于自定義了scheme,對于前端來說,需要額外將scheme設置為我們自定義的,這又會給前端帶來大量的改造,所以對前端還是產(chǎn)生了入侵。
上面提到在安卓完全不需要像iOS這樣大費周章的繞彎路,所以安卓可能就不需要這個自定義的scheme,這樣又會導致面臨著與安卓差異化嚴重問題。
所以這樣來看,WKURLSchemeHandler的攔截方案也并不是特別友好。真的是感覺到了蘋果爸爸對于離線包的惡意
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/7360.html
摘要:提及緩存時,不僅僅是指存儲,還包括瀏覽器內(nèi)用來保存數(shù)據(jù)以供離線使用的策略。當請求成功返回時,利用返回的數(shù)據(jù)更新頁面并緩存返回的數(shù)據(jù)。這種方案主要應用用戶頻繁手動更新內(nèi)容的場景,比如用戶的收件箱或者文章內(nèi)容。我們打算應用的策略。 上一篇文章中,我們成功嘗試使用 service workers。我們也可以在應用中緩存一些資源。這篇文章我們準備了解這些:service workers 以及緩...
摘要:前端每周清單第期微服務實踐,與,組件技巧,攻防作者王下邀月熊編輯徐川前端每周清單專注前端領域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點分為新聞熱點開發(fā)教程工程實踐深度閱讀開源項目巔峰人生等欄目。 前端每周清單第 26 期:Node.js 微服務實踐,Vue.js 與 GraphQL,Angular 組件技巧,HeadlessChrome 攻防 作者:王下邀月熊 編輯:徐川...
摘要:數(shù)據(jù)浪潮之間的前端工程師十年來,波瀾壯闊的移動互聯(lián)網(wǎng)浪潮促進了技術的迅猛發(fā)展,隨著瀏覽器性能網(wǎng)絡帶寬等基礎設施的提升,也能夠承載起包含復雜交互可視化計算邏輯需求的富客戶端應用。 showImg(https://segmentfault.com/img/remote/1460000016874425); 本文是架構(gòu)師 2018-10 月刊的卷首語,歸納于自筆者的技術之路系列文章,也是對 ...
閱讀 3518·2023-04-25 15:52
閱讀 588·2021-11-19 09:40
閱讀 2612·2021-09-26 09:47
閱讀 1034·2021-09-22 15:17
閱讀 3557·2021-08-13 13:25
閱讀 2232·2019-08-30 15:56
閱讀 3472·2019-08-30 13:56
閱讀 2111·2019-08-30 11:27