Service Worker

當下PWA比較火,而Service Worker是實現PWA的一項關鍵技術,今天我們一起了解下關於Service Worker的一些基礎知識和適用場景。

什麼是Server Worker

我們先來看一下官方文檔中對於Server Worker的核心定義:

Service workers 本質上充當Web應用程序與瀏覽器之間的代理服務器,也可以在網絡可用時作爲瀏覽器和網絡間的代理。

這是一條很準確的定義,但對於不瞭解Service Worker的同學來說可能並不形象,下面我們更形象的理解一下這個概念。我們以去銀行取錢爲例子,其過程大概如下圖:

從上面的圖中我們可以看到,銀行的錢存在金庫中,客戶取錢時並不是直接去金庫裏拿,而是需要通過銀行的工作人員,再告知銀行工作人員需要多少錢,並出示相應憑證後,由銀行工作人員從金庫中拿出錢給客戶,並從賬戶中減去相應金額。這麼做的原因很容易理解,因爲金庫是公用的,所有客戶的錢都放在裏面,我們無法保證每個客戶都能只拿走屬於自己的錢,並按照實際情況更新金庫記錄。

我們的應用在請求服務器資源時,其過程也是類似的:

從上面的圖可以看到,請求資源的過程中,HTTP協議充當了取錢過程中的銀行工作人員,客戶端應用需要的資源在服務器上,但應用卻無法直接去服務器獲取資源,而是通過HTTP協議進行,請求中指定的各種Header信息,就是取錢時的憑證。

而Service Worker可以理解成,在客戶端創建了一個屬於自己的金庫,先看圖:

當我們需要取錢或者獲取資源時,可以先從本地的金庫中拿,本地金庫沒有,再通過原來的流程獲取。這時我們再回頭看文章開始的定義,應該就能夠理解了。

Service Worker與Cache的關係

正常情況下,客戶端獲取一個資源的過程有如下三步:

而關於請求資源的優化,一般也集中在這三步完成:

  1. 不發出請求就能夠獲得資源;
  2. 提高服務器查找資源的速度;
  3. 減小返回內容的體積;

看完上面的部分我們可以發現,當使用Service Worker中已有的資源時,客戶端應用獲取資源並沒有進入HTTP請求的流程,也就是說,通過Service Worker,客戶端應用可以在不發出請求的情況下獲得資源,這很容易就讓我們想到緩存,那麼Service Worker和我們平時經常提到的強緩存和協商緩存等是什麼關係呢?整理了一個圖,可以先看下:

從整體上來說,應用獲取一個資源的緩存類型分爲上圖中的四種,分別是Service Worker、Memory Cache、Disk Cache和No Cache。資源查找順序爲從左向右,找到資源則返回,未找到則繼續尋找,直至最終獲取資源。上面的圖中可以清楚的看出Service Worker在緩存類型中的位置,也能看到跟平時經常提到的強緩存和協商緩存的關係。

Service Worker使用邏輯

在瞭解了Service Worker的概念後,我們看下Servise Worker的基本使用邏輯,使用它的基礎過程是首先註冊一個Woker,這時瀏覽器會在後臺啓動一個新的線程,在這個線程啓動後,會按照Service Worker中的代碼邏輯將一些資源緩存下來,緩存完畢後,啓動對頁面請求的監聽,當監聽到頁面請求資源時可以做出相對應的響應,比如如果資源在Service Worker中緩存過了,就可以直接返回資源。

註冊

Service Worker對象保存在window.navigator內,首先調用register方法進行註冊,導入一個js文件,文件中是我們的Service Worker邏輯,代碼如下:

navigator.serviceWorker.register('/sw.js')
.then(function(reg){
    console.log("success", reg);
}).catch(function(err) {
    console.log("error", err);
});

需要注意的是Service Worker是有作用域的,它的作用域爲文件的當前路徑,Service Worker文件只能管理自己作用下的資源,比如abcde.com/home/sw.js 的作用域爲abcde.com/home/。

激活

註冊後的Service Worker就能在調試工具中看到了,下面是一個chrome調試面板的截圖:

畫紅框的內容是一些比較關鍵的信息,比如其中表明瞭Service Worker的文件名和路徑,以及當前Service Worker的狀態,Service Worker的狀態分爲幾種,STOPPED(已停止)、STARTING(正在啓動)、RUNNING(正在運行)和STOPPING(正在停止),比如上面的截圖就處於RUNNING狀態。

只有處於running狀態的Service Worker才能生效,這就需要對註冊後的Service Worker進行加載和激活,註冊完畢後,Service Worker會自動開始下載,下載後會觸發install事件,我們可以監聽這個事件並進行下載資源的操作,代碼如下:

const CACHE_NAME = "demo-a";
this.addEventListener("install", function(event) {
    console.log("install service worker success");
    caches.open(CACHE_NAME);
    let cacheResources = ["https://abcde.com/demo.js"];
    event.waitUntil(
        caches.open(CACHE_NAME).then(cache => {
            cache.addAll(cacheResources);
        })
    );
});

經過上面的代碼,demo.js文件就被我們緩存下來了,下載完後Service Worker就會執行激活:

this.addEventListener("active", function(event) {
    console.log("service worker active success");
});

此時我們通過開發者工具就能看到一個激活的Service Worker了,整體梳理一下大概是下面的過程:

需要注意的是,圖中灰色的部分是一個獨立的特殊線程,並不是瀏覽器渲染頁面執行js的線程,因此使用Service Worker的過程中無需擔心會影響頁面的渲染。

更新

我們註冊了Service Worker後,還面臨着更新的問題,當我們的業務迭代時必然要更新Service Worker,在我們理解了它的整個註冊過程後,理解更新就很簡單了,直接上圖:

當應用加載時,會下載Service Worker文件,這是在瀏覽器中就會有兩個文件,一個是當前正在使用的Service Worker,一個是新下載的Service Worker,當新下載的文件下載完畢後,瀏覽器會對兩個文件進行Diff操作,如果發現文件沒有更新,則會丟棄掉新下載的Service Worker文件,如果發現有變化,則會加載新的Service Worker,但新加載的Service Worker會處於wating狀態,並不會實際發揮作用,只有當整個瀏覽器中對正在運行的Service Worker沒有依賴時,纔會將運行中的Service Worker拋棄,將新的Servier Worker置爲激活狀態。

常見使用場景

  1. 用於瀏覽器緩存,提高加載速度;
  2. 實現離線應用,最近PWA如此火爆;
  3. 實現消息的主動推送,爲web應用增加一種給力的交互方式;

兼容性

我們瞭解一些Service Worker的基礎知識,以及一些比較常見的使用場景,那麼目前Service Worker的兼容性如何呢,看下圖

目前主流的現代瀏覽器支持度還是不錯的,但是到目前爲止全系列的IE瀏覽器均不支持Service Worker,而且有一點感受很明顯,在查資料的過程中,看了網上不少的博客,不同的博客上也有當時寫博客時的Service Worker支持度,可以明顯感覺到Service Worker的支持程度在快速提升,隨着支持度的提升,相信會有越來越多的開發者在項目中使用這項技術。

藉助Service Worker,真正讓PWA應用變得流行,也許就在不久的將來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章