Service Worker

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

什麼是Server Worker

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

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

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

從上面的圖中咱們能夠看到,銀行的錢存在金庫中,客戶取錢時並非直接去金庫裏拿,而是須要經過銀行的工做人員,再告知銀行工做人員須要多少錢,並出示相應憑證後,由銀行工做人員從金庫中拿出錢給客戶,並從帳戶中減去相應金額。這麼作的緣由很容易理解,由於金庫是公用的,全部客戶的錢都放在裏面,咱們沒法保證每一個客戶都能只拿走屬於本身的錢,並按照實際狀況更新金庫記錄。緩存

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

從上面的圖能夠看到,請求資源的過程當中,HTTP協議充當了取錢過程當中的銀行工做人員,客戶端應用須要的資源在服務器上,但應用卻沒法直接去服務器獲取資源,而是經過HTTP協議進行,請求中指定的各類Header信息,就是取錢時的憑證。網絡

而Service Worker能夠理解成,在客戶端建立了一個屬於本身的金庫,先看圖:工具

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

Service Worker與Cache的關係

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

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

  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應用變得流行,也許就在不久的未來。

相關文章
相關標籤/搜索