Service Workers - JavaScript API 簡介

做者: Felix Gerschau
譯者:前端小智
來源:Felix Gerschau

最近開源了一個 Vue 組件,還不夠完善,歡迎你們來一塊兒完善它,也但願你們能給個 star 支持一下,謝謝各位了。javascript

github 地址:https://github.com/qq44924588...css

service worker 是什麼

Service Worker 是 Chrome 團隊提出和力推的一個 WEB API,用於給 web 應用提供高級的可持續的後臺處理能力。該 WEB API 標準起草於 2013 年,於 2014 年歸入 W3C WEB 標準草案,當前還在草案階段。html

Service Worker 最主要的特色是:在頁面中註冊並安裝成功後,運行於瀏覽器後臺,不受頁面刷新的影響,能夠監聽和截攔做用域範圍內全部頁面的 HTTP 請求。前端

相似一個服務器與瀏覽器之間的中間人角色,若是網站中註冊了service worker 那麼它能夠攔截當前網站全部的請求,進行判斷(須要編寫相應的判斷程序),若是須要向服務器發起請求的就轉給服務器,若是能夠直接使用緩存的就直接返回緩存再也不轉給服務器。從而大大提升瀏覽體驗。vue

圖片描述

Service Worker 能夠啓用之前原生應用程序專有的一組功能。 Service Worker 的初稿已於2014年發佈,如今全部主流瀏覽器都支持它們。java

就像已經指出的定義同樣,Service Worker 是網絡代理。 這意味着它們能夠控制頁面中的全部網絡請求,而且能夠對其進行編程,使用緩存的進行響應。git

Service Worker 特色

  • 網站必須使用 HTTPS。除了使用本地開發環境調試時(如域名使用 localhost)
  • 運行於瀏覽器後臺,能夠控制打開的做用域範圍下全部的頁面請求
  • 單獨的做用域範圍,單獨的運行環境和執行線程
  • 不能操做頁面 DOM。但能夠經過事件機制來處理

如何註冊 Service Worker

註冊 Service Worker 不須要太多代碼,只須要一個用於Service Worker 代碼的 JS 文件,通常取名爲 service-worker.jsgithub

// 首先檢查瀏覽器是否支持 Service Worker
if ('serviceWorker' in navigator) {
  navigator.serviceWorker
    .register('/sw/service-worker.js')
    .then(function(registration) {
      console.log(registration);
    })
    .catch(function(err) {
      console.log(err);
    });
}

其實關鍵代碼只有一行:web

navigator.serviceWorker.register('/sw/service-worker.js')

注意:面試

Service Worker 的註冊路徑決定了其 scope 默認做用範圍。示例中 service-worker.js 是在 /sw 路徑下,這使得該 Service Worker 默認只會收到 /sw 路徑下的 fetch事件。若是存放在網站的根路徑下,則將會收到該網站的全部 fetcg事件。

若是但願改變它的做用域,可在第二個參數設置 scope範圍。示例中將其改成了根目錄,即對整個站點生效。

另外應意識到這一點:Service Worker 沒有頁面做用域的概念,做用域範圍內的全部頁面請求都會被當前激活的 Service Worker 所監控。

Service Worker 能夠啓用哪些功能?

在本節中,我將進一步詳細介紹Service Worker的功能,包括一些小代碼示例。

服務工做者啓用如下功能,這些功能也是 PWA的核心:

  • 離線功能
  • 按期後臺同步
  • 推送通知

離線功能

Service Worke 經過緩存資源和攔截網絡請求來提供離線功能,這些請求能夠與先前緩存的資源一塊兒使用,而不是從新請求服務器。

咱們能夠從中得出兩個步驟:

  • 預緩存
  • 從緩存中處理請求

這兩個步驟都利用了Cache API,它由 Web Workers 和瀏覽器使用,而且爲咱們提供了用於網絡請求的存儲機制。

對 Web 和服務工做人員上下文的 localStorage 訪問被阻止,以防止併發性問題。做爲一種替代方案,IndexedDB 能夠用於存儲大量數據。

預緩存

預緩存是一個術語,描述了在 Service Worker 處於激活狀態以前下載和緩存文件。 它是在 Service Worker 生命週期的「install 」步驟中完成的。 一旦 Service Worker 處於激活狀態,它將準備爲緩存中的文件提供服務。

一般,咱們要緩存 Application Shell,這是運行網站所需的最少代碼量。 若是開發了本機應用程序,那麼這就是您將上傳到應用程序商店的代碼包。 這包括全部必需的基本JavaScript,HTML和圖片。

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(currentCache.offline).then(function(cache) {
      return cache.addAll([
        '/static/images/offline.svg',
        '/static/html/offline.html',
      ]);
    });
  );
});

從緩存中處理請求

在此階段,咱們已經將全部應用程序代碼存儲在緩存中,而且Service Worker 已處於激活即運行於瀏覽器後臺。

如今惟一缺乏的是監聽 fetch 事件並從緩存中返回結果。能夠經過 fetch 事件能夠攔截到當前做用域範圍內的 http/https 請求,而且給出本身的響應。結合 Fetch API ,能夠簡單方便地處理請求響應,實現對網絡請求的控制。

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(response) {
      return response || fetch(event.request);
    })
  );
});

在本例中,咱們儘量使用緩存的內容進行響應。做爲回退,咱們發出一個網絡請求。

這裏實現了一個緩存優先降級處理的策略邏輯:監控全部 http 請求,當請求資源已經在緩存裏了,直接返回緩存裏的內容;不然使用 fetch API 繼續請求,若是是 圖片或 cssjs 資源,請求成功後將他們加入緩存中;若是是離線狀態或請求出錯,則降級返回預緩存的離線內容。

按期後臺同步

正如在引言中已經提到的那樣,Service Worker 與其餘服務工做者在一個單獨的線程上運行,因此即便關閉頁面,它們也能夠執行其代碼。 此功能對於執行後臺同步和提供推送通知很重要。

後臺同步

用戶離開頁面後,後臺同步一般用於同步數據。

例如,在手機上編輯文檔後,咱們寫完會點擊「保存」並離開頁面。 若是在編輯文檔期間鏈接斷開,咱們必須等待鏈接恢復才能保存文檔。

後臺同步的目的是解決這個問題,一旦鏈接從新創建,自動發送數據。

來看一個示例:

app.js

navigator.serviceWorker.ready.then((registration) => {
  return registration.sync.register('sync-save-document');
});

service-worker.js

self.addEventListener('sync', (event) => {
  if (event.tag === 'sync-save-document') {
    event.waitUntil(saveDocument());
  }
});

saveDocument是一個返回 Promise,若是被拒絕(例如因爲網絡問題),同步將自動重試。

要注意的一件事是,同步標記必須是惟一的。 例如,若是我要安排5個「message」類型的後臺同步,則只有最後一個會經過。 所以,在這種狀況下,每一個標籤都應具備惟一的標識符。

按期後臺同步

按期後臺同步解決與正常後臺同步不一樣的問題。 該API可用於在後臺更新數據,而沒必要等待用戶。

這對不少應用程序都頗有用。有了這項技術,用戶能夠在沒有互聯網鏈接的狀況下閱讀最新的新聞文章。

爲了防止濫用這一功能,同步的頻率取決於瀏覽器爲每一個網站設置的站點參與度分數。若是你常常打開一個網頁應用,這個頻率最多能夠達到12個小時。

要實現此目的一個要求是,該網站已做爲移動設備上的 PWA 安裝並添加到主屏幕。

推送通知

Service Worker另外一個相似本機的特性是推送通知。咱們一般經過手機短信或社交媒體通知的形式知道它們,但它們也能夠在臺式電腦上使用。

Safari以外,全部主流瀏覽器都支持它們,而Safari對桌面應用程序有本身的實現。

要使用推送通知,須要設置一臺服務器,該服務器會將通知推送給全部客戶端。 因爲Service Worker在後臺在另外一個線程上運行,所以即便頁面當前未打開,用戶也能夠看到推送通知。

推送的實現有兩步:

不一樣瀏覽器須要用不一樣的推送消息服務器。以 Chrome 上使用 Google Cloud Messaging<GCM> 做爲推送服務爲例,第一步是註冊 applicationServerKey(經過 GCM 註冊獲取),並在頁面上進行訂閱或發起訂閱。每個會話會有一個獨立的端點(endpoint),訂閱對象的屬性(PushSubscription.endpoint) 即爲端點值。將端點發送給服務器後,服務器用這一值來發送消息給會話的激活的 Service Worker (經過 GCM 與瀏覽器客戶端溝通)。

瀏覽器支持狀況

clipboard.png

除了 Safari 和 IE/Edge,大部分現代瀏覽器都已經獲得了支持。

總結

但願經過本文介紹基本概念和特性,可讓你更好地理解Service Worker


代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

原文:https://felixgerschau.com/ser...

交流

文章每週持續更新,能夠微信搜索「 大遷世界 」第一時間閱讀和催更(比博客早一到兩篇喲),本文 GitHub https://github.com/qq449245884/xiaozhi 已經收錄,整理了不少個人文檔,歡迎Star和完善,你們面試能夠參照考點複習,另外關注公衆號,後臺回覆福利,便可看到福利,你懂的。

相關文章
相關標籤/搜索