天天看點

Service Worker簡介

介紹

Service Workder相當于浏覽器與web應用程式之間的代理伺服器,可以捕獲請求事件并做相應處理;目前主要用于離線應用以及消息推送及背景同步等;

特性

  1. 無法直接通路和操作DOM
  2. 在長時間不用時會被中止并在下次需要時重新開機;
  3. 可以通路和操作

    indexedDB API

  4. 推薦使用HTTPS
  5. 内部實作基于

    Promise

生命周期

  1. install

    事件是SW的第一個事件,隻會發生一次,使用

    e.waitUtil()

    監測是否安裝成功;
  2. 生命周期中的主要圍繞兩個事件

    install

    activate

    install

    前後的生命周期包括

    installing

    installed

    activate

    前後的生命周期包括

    activating

    activated

    ;最後SW不用或者新舊更替時經曆的生命周期時

    redundant

  3. 在安裝成功并處于

    活動狀态

    之前,不會處理

    functional events

  4. 處于

    activated

    狀态才可以處理

    functional events: fetch/push/sync

Service Worker簡介

支援的事件

Service Worker簡介

使用

demo位址

  1. 注冊

    可以通過

    serviceWorker.register()

    方法注冊一個

    Service Worker

    執行個體,它是由

    Promise

    實作的,

    resolve

    後在

    then

    函數中拿到

    registration

    對象;包含了所注冊sw的相關資訊,如下圖:
    Service Worker簡介
    具體注冊實作的過程如下圖:
    if ('serviceWorker' in navigator) {
        window.addEventListener('load', () => {
            navigator.serviceWorker.register('sw.js')
            .then(registration => {
                console.log('sw installed: ', registration);
            })
            .catch(err => console.log('sw installed failed: ', err))
        })
    }
    
               
  2. 安裝 Service Worker

    在本文生命周期一節中,根據圖示我們看到

    install

    事件中可以通過

    event.waitUntil()

    方法建立一個Promise對象來等待安裝完成,安裝完成後則

    Promise

    resolve

    ,然後我們可以打開緩存并存緩存需要緩存的資源;

    具體實作如下:

    var CACHE_NAME = 'sw-cache';
    var CACHE_URLS = ['./index.html', './index.js', './public/equal.png', './public/icon.png'];
    self.addEventListener('install', e => {
    	e.waitUntil(
    		caches.open(CACHE_NAME)		// 打開緩存
    		.then(cache => cache.addAll(CACHE_URLS))
    	)
    }
               
  3. 捕獲請求并處理

    具體實作如下:

    self.addEventListener('fetch', e => {
    	e.respondWith(
    		caches.match(e.request)	// 檢測緩存資源和請求資源是否比對, e.request具有以下屬性:url/method/header/body
    		.then(res => {
    			if (res) {
    				return res;
    			}
    			console.log('loaded from sw');
    		})
    	)
    })
               
  4. 更新
    1. 自動更新

      Service Workder

      的更新遵循以下步驟(來自谷歌開發者):
      1. 更新您的服務工作線程 JavaScript 檔案。 使用者導航至您的站點時,浏覽器會嘗試在背景重新下載下傳定義 Service Worker 的腳本檔案。 如果 Service Worker 檔案與其目前所用檔案存在位元組差異,則将其視為新 Service Worker。
      2. 新 Service Worker 将會啟動,且将會觸發 install 事件。
      3. 此時,舊 Service Worker 仍控制着目前頁面,是以新 Service Worker 将進入 waiting 狀态。
      4. 當網站上目前打開的頁面關閉時,舊 Service Worker 将會被終止,新 Service Worker 将會取得控制權。
      5. 新 Service Worker 取得控制權後,将會觸發其 activate 事件。
      下圖可以看到:當我們更新了sw.js檔案後,新的sw處于

      waiting to active

      的狀态,而舊的sw仍然運作并且處于

      active

      狀态;
      Service Worker簡介
      關閉上圖中的标簽頁

      http://127.0.0.1:5500/service%20worker/index.html

      并重新打開頁面後:如下圖,我們可以看到新的id為128的sw已經運作并處于

      active

      狀态;
      Service Worker簡介
      當然,可以通過調用

      self.skipWaiting()

      跳過等待階段,在安裝完成後立即激活;
    2. 手動更新
      navigator.serviceWorker.register('/sw.js').then(reg => {
      	// something later
      	reg.update();
      })
                 
  5. 删除舊緩存

    由于浏覽器對

    Service Worker

    可用的磁盤空間有嚴格限制,是以更新

    Service Worker

    時,我們需要進行緩存管理;

    根據

    Service Worker

    的生命周期,我們可以看到在

    active

    階段

    Service Worker

    處于活躍狀态,即可以管理舊sw相關的資源;
    self.addEventListener('activate', function(event) {
    	// 建立需要儲存的緩存白名單
      var cacheWhitelist = ['pages-cache-v1', 'blog-posts-cache-v1'];
    
      event.waitUntil(
        caches.keys().then(function(cacheNames) {
          return Promise.all(
            cacheNames.map(function(cacheName) {
              if (cacheWhitelist.indexOf(cacheName) === -1) {
                return caches.delete(cacheName);
              }
            })
          );
        })
      );
    });
               

效果示範

Service Worker簡介

參考文獻:

  1. https://developers.google.com/web/fundamentals/primers/service-workers/?hl=zh-CN
  2. https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers
  3. https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle?hl=zh-CN

繼續閱讀