H5 開發(fā)的 App 中調(diào)用 Android WebView 時的相關(guān)優(yōu)化

前段時間用 ionic 開發(fā)了一個 App,當(dāng)時需要調(diào)用 WebView 來顯示一些內(nèi)容(本來采用的 iframe 方案,由于很多網(wǎng)站已經(jīng)禁用了 iframe 且這種方式不太安全可靠,后來想想還是改用 WebView 了)。WebView 下有很多問題啊,一是樣式和 ionic 不太匹配,而是性能上顯得奇慢,突出表現(xiàn)為耗費大量流量而且加載慢。樣式匹配的問題有現(xiàn)成解決方案,本篇主要針對當(dāng)時遇到的性能問題給出一些建議。

H5 頁面加載慢的原因

原因有兩個方面:

  • 自身渲染速度慢,比如解析 js 腳本,還有手機或者其他硬件設(shè)備的性能
    • 如果 js 腳本過于復(fù)雜,前端又包含大量 js 腳本的話,會影響渲染速度
    • 手機等硬件問題就不說了,尤其是 Android 手機
  • 資源加載慢,主要是因為 H5 頁面請求數(shù)量太多(包括 js、css 等一系列資源文件)
    • 基本 url 請求
    • css、js 甚至圖片視頻等資源文件
    • 這些請求是串行的,不請求完不行

一些解決辦法

  1. Android WebView 自身有一個緩存機制
  2. H5 頁面的預(yù)加載

Android WebView 緩存

緩存的好處有兩個:

  • 加載過后沒有網(wǎng)絡(luò)連接時也能訪問
  • 提高訪問速度并減少流量損耗

Android WebView 緩存機制其實也就是 H5 頁面的緩存機制,主要有5種:

  1. 瀏覽器緩存

    瀏覽器緩存主要依賴 Http 頭中 Cache-Control (Expires)和 Last-Modified(Etag) 等字段來控制

    Cache-Control:文件在本地緩存的時間

    Expires:同 Cache-Control 一樣,前者優(yōu)先級更高,是 http1.1 協(xié)議之后增加的字段

    Last-Modified:文件在服務(wù)器上最新更新時間,當(dāng)本地緩存過期時,發(fā)送 If-Modified-Since 字段帶上時間給服務(wù)器,服務(wù)器判斷文件是否更新過,沒有更新服務(wù)器會返回304,有更新返回200,并返回最新更新的文件

    Etag:功能同 Last-Modified

    常用做法:Cache-Control 與 Last-Modified 一起用,Expires 和 Etag 一起使用

    優(yōu)點:不需要你過多考慮,只要在協(xié)議上設(shè)定好

    缺點:一是必須要首次加載之后,二是緩存被清之后還要加載,三是加載別人的網(wǎng)頁時協(xié)議不由你設(shè)定啊

    場景:加載靜態(tài)資源時,可以考慮,如 JS、CSS、圖片等

    實現(xiàn):不需要你考慮,WebView 自帶瀏覽器自動實現(xiàn)

  2. Application Cache 緩存

    Appliaction Cache 是一種以文件為緩存,且文件有一定更新機制的緩存機制,是專門用于 WebApp 緩存的機制。在 HTML 文件頭部用 manifest 說明,是瀏覽器緩存的一種補充

    優(yōu)點:同上

    缺點:同上

    場景:同上

    實現(xiàn):通過設(shè)置 WebView 的 settings 來實現(xiàn)。

    WebSettings settings = getSettings();
    String cacheDir = context.getFilesDir().getAbsolutePath()+"cache/";
    settings.setAppCachePath(cacheDir);
    settings.setAppCahceMax(50*1024*1024);
    settings.setAppCacheEnabled(true);
    
  3. Dom Storage 緩存

    Dom Storage 通過 key-value 的形式來存儲字符串,分為兩種:

    • sessionStorage:臨時性,頁面關(guān)閉后無法使用
    • localStorage:持久性,頁面關(guān)閉后仍能使用

    其存儲空間對于不同瀏覽器不同

    優(yōu)點:相對于 cookie 來說,存儲空間更大,不用和 cookie 一樣每次都向服務(wù)器發(fā)送請求。存在本地,相對安全穩(wěn)定

    缺點:同上

    應(yīng)用場景:取代 cookie 機制。存儲簡單、臨時的數(shù)據(jù)。

    實現(xiàn):還是設(shè)置 WebView 的 settings

    WebSettings settings = getSettings();
    settings.setDomStorageEnabled(true);
    
  4. Web SQL Database 緩存

    Web SQL Database 實質(zhì)上是一種基于 SQL 的數(shù)據(jù)庫存儲機制,適合于結(jié)構(gòu)化數(shù)據(jù)的存儲

    優(yōu)點:充分利用數(shù)據(jù)庫特點,方便增刪改查

    缺點:同上,且官方不再維護,取而代之是 Indexed Database 緩存機制

    應(yīng)用場景:存儲結(jié)構(gòu)化數(shù)據(jù)

    實現(xiàn):依然是設(shè)置 WebView 的 settings

    WebSettings settings = getSettings();
    String cacheDir = context.getFilesDir().getAbsolutePath()+"cache/";
    settings.setDatabaseEnabled(true);
    
  5. Indexed Database 緩存

    Indexed Database 屬于 NoSQL 數(shù)據(jù)庫,也是通過 key-value 的形式來提供的

    優(yōu)點:存儲空間大,默認(rèn)推薦是250M存儲空間,可以生成索引,同樣可以像操作數(shù)據(jù)庫一樣操作數(shù)據(jù),采用異步的 API 調(diào)用,用戶體驗較好

    缺點:同上

    應(yīng)用場景:存儲復(fù)雜、結(jié)構(gòu)化的數(shù)據(jù)

    實現(xiàn):都是設(shè)置 WebView 的 settings

    WebSettings settings = getSettings();
    settings.setJavaScriptEnabled(true);
    // what?? 只要設(shè)置支持 JS 就能自動打開 IndexedDB 存儲機制,神奇不神奇?
    
關(guān)于 Android WebView 自身緩存機制總結(jié)

我們可以根據(jù)不同的場景設(shè)置不同的緩存機制,也可以組合使用,通常的做法是醬的:

  • 存儲靜態(tài)資源
    • 瀏覽器緩存
    • Application Cache
  • 存儲臨時簡單數(shù)據(jù)
    • Dom Storage
  • 存儲復(fù)雜數(shù)據(jù)量大的數(shù)據(jù)
    • IndexedDB Storage

H5 頁面預(yù)加載

可是以上方案都是第一次加載依然很慢咋辦?為了提升這個體驗,我們產(chǎn)生了 資源預(yù)加載 的方案

它是怎么實現(xiàn)的呢?具體的 App 有具體自己的方式

一種方式是通過攔截 H5 頁面的資源網(wǎng)絡(luò)請求,從而從本地讀取資源而不是從網(wǎng)絡(luò)讀取

一種實現(xiàn)就是,首先將頻率更新低、常用且固定的靜態(tài)資源文件放到本地,攔截 H5 頁面資源網(wǎng)絡(luò)請求,如果檢測到有相同的靜態(tài)資源,直接使用本地的,不再發(fā)送請求。

舉個栗子:很多微信就是采取這樣的方案來解決問題的,圖片和視頻等資源文件在 wifi 才加載或者最后才加載

Demo 可以參考 https://github.com/Carson-Ho/WebView_InterceptRequest

當(dāng)然,在我開發(fā) ionic App 的時候,沒法修改這些 WebView 設(shè)置啊之類的這么做,但是也想用預(yù)加載啊,怎么辦?沒事,預(yù)加載的沒有具體實現(xiàn),它只是一個思路,具體情況具體分析。

比如像我這樣的情況:ionic 沒法修改 WebView 設(shè)置,僅僅是能調(diào)用 WebView,我打開的 url 是外部 url,不是自己的網(wǎng)站,靜態(tài)資源和腳本是別人網(wǎng)站設(shè)置的不由我控制

我的解決方案(僅供參考):在 App 啟動時,當(dāng)加載完數(shù)據(jù)之后,后臺默默啟動一個 WebView ,提前將需要訪問的網(wǎng)站(第一頁假如有20個網(wǎng)頁)訪問一遍,使其在瀏覽器中留有緩存,當(dāng)我在瀏覽這一頁時,WebVIew 就把下一頁的網(wǎng)頁提前訪問一遍。醬就感覺快多了。

最后編輯于
?著作權(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ù)。

相關(guān)閱讀更多精彩內(nèi)容

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