?上一篇我們講解了如何在前端做項目優化,這篇來接著講在客戶端應該如何優化?
客戶端優化
接著輪到客戶端出場了,桌面時代受限于瀏覽器,H5 頁面無法做更多的優化,現在 H5 頁面是內嵌在客戶端 APP 上,客戶端有更多的權限,于是客戶端上可以超出瀏覽器的范圍,做更多的優化。
HTML 緩存
先接著緩存說,在客戶端有更自由的緩存策略,客戶端可以攔截 H5 頁面的所有請求,由自己管理緩存,針對上述 HTML 文件的“緩存”和“更新”之間的矛盾,我們可以用這樣的策略解決:
1.在客戶端攔截請求,首次請求 HTML 文件后緩存數據,第二次不發請求,直接使用緩存數據。
2.什么時候去請求更新?這個更新請求可以客戶端自由控制策略,可以在使用本地緩存打開本地頁面后再在后臺發起請求詢問更新緩存,下次打開時生效;也可以在 APP 啟動時或某個時機在后臺去發起請求預更新,提升用戶訪問最新代碼的幾率。
這樣看起來已經比較完美了,HTML 文件在用客戶端的策略緩存,其余資源和數據沿用上述前端的緩存方式,這樣一個 H5 頁面第二次訪問從 HTML 到 JS/CSS/Image 資源,再到數據,都可以直接從本地讀取,無需等待網絡請求,同時又能保持盡可能的實時更新,解決了緩存問題,大大提升 H5 頁面首屏啟動速度。
問題
上述方案似乎已完整解決緩存問題,但實際上還有很多問題:
1.沒有預加載:第一次打開的體驗很差,所有數據都要從網絡請求。
2.緩存不可控:緩存的存取由系統 webview 控制,無法控制它的緩存邏輯,帶來的問題包括:
清理邏輯不可控,緩存空間有限,可能緩存幾張大圖片后,重要的 HTML/JS/CSS 緩存就被清除了。
磁盤 IO 無法控制,無法從磁盤預加載數據到內存。
更新體驗差:后臺 HTML/JS/CSS 更新時全量下載,數據量大,弱網下載耗時長。
無法防劫持:若 HTML 頁面被運營商或其他第三方劫持,將長時間緩存劫持的頁面。
這些問題在客戶端上都是可以被解決的,只不過有點麻煩,簡單描述下:
1.可以配置一個預加載列表,在APP啟動或某些時機時提前去請求,這個預加載列表需要包含所需 H5 模塊的頁面和資源,還需要考慮到一個H5模塊有多個頁面的情況,這個列表可能會很大,也需要工具生成和管理這個預加載列表。
2.客戶端可以接管所有請求的緩存,不走 webview 默認緩存邏輯,自行實現緩存機制,可以分緩存優先級以及緩存預加載。
3.可以針對每個 HTML 和資源文件做增量更新,只是實現和管理起來比較麻煩。
4.在客戶端使用 httpdns + https 防劫持。
上面的解決方案實現起來十分繁瑣,原因就是各個 HTML 和資源文件很多很分散,管理困難,有個較好的方案可以解決這些問題,就是離線包。
離線包
既然很多問題都是文件分散管理困難引起,而我們這里的使用場景是使用 H5 開發功能模塊,那很容易想到把一個個功能模塊的所有相關頁面和資源打包下發,這個壓縮包可以稱為功能模塊的離線包。使用離線包的方案,可以相對較簡單地解決上述幾個問題:
1.可以預先下載整個離線包,只需要按業務模塊配置,不需要按文件配置,離線包包含業務模塊相關的所有頁面,可以一次性預加載。
2.離線包核心文件和頁面動態的圖片資源文件緩存分離,可以更方便地管理緩存,離線包也可以整體提前加載進內存,減少磁盤 IO 耗時。
3.離線包可以很方便地根據版本做增量更新。
4.離線包以壓縮包的方式下發,同時會經過加密和校驗,運營商和第三方無法對其劫持篡改。
到這里,對于使用H5開發功能模塊,離線包是一個挺不錯的方案了,簡單復述一下離線包的方案:
1.后端使用構建工具把同一個業務模塊相關的頁面和資源打包成一個文件,同時對文件加密/簽名。
2.客戶端根據配置表,在自定義時機去把離線包拉下來,做解壓/解密/校驗等工作。
3.根據配置表,打開某個業務時轉接到打開離線包的入口頁面。
4.攔截網絡請求,對于離線包已經有的文件,直接讀取。
5.離線包數據返回,否則走 HTTP 協議緩存邏輯。
離線包更新時,根據版本號后臺下發兩個版本間的 diff 數據,客戶端合并,增量更新。
光做完這兩個對于優化還是完全不足夠的,不僅僅是在前端和客戶端是需要做優化,還有細節方面也是需要做優化的。這一節就講到這,稍后再給大家講講。