JavaScript是如何工做的:Service Worker的生命週期及使用場景

摘要: 理解Service Worker。javascript

Fundebug經受權轉載,版權歸原做者全部。前端

這是專門探索 JavaScript 及其所構建的組件的系列文章的第8篇。java

若是你錯過了前面的章節,能夠在這裏找到它們:web

你可能已經知道,漸進式Web應用程序 只會愈來愈受歡迎,由於它們的目標是讓Web應用程序用戶體驗更流暢,建立相似於原生應用程序的體驗,而不是瀏覽器的外觀和感受。編程

構建漸進式Web應用程序的主要要求之一是使其在網絡和加載方面很是可靠——它應該在不肯定或不存在的網絡條件下可用。小程序

在這篇文章中,將深刻探討 Service Workers:它們是如何工做,你應該關心什麼。最後,還列出了 Service Workers 中的一些獨特優勢在哪些場景下是值得咱們使用的。segmentfault

簡介

若是你還想了解更多 Service Workers 的知識,能夠閱讀做者關於 Web Workers 的文章。微信小程序

Service Worker是什麼數組

MDN 的介紹:promise

Service Worker 是一個瀏覽器背後運行的腳步,獨立於 web 頁面,爲無需一個頁面或用戶交互的功能打開了大門。今日,它包含了推送通知和背景異步(push notifications and background sync)的功能。未來,Service Worker 將支持包括 periodic sync or geofencing 的功能。

基本上,Service Worker 是 Web Worker 的一個類型,更具體地說,它像 Shared Worker

  • Service Worker 在其本身的全局上下文中運行
  • 它沒有綁定到特定的網頁
  • 它不能訪問到 DOM

這是一個使人興奮的 API 的緣由是它容許你支持離線體驗,讓開發人員徹底控制體驗。

Service Worker 的生命週期

Service Worker 的生命週期與 web 頁面徹底分離。它包括如下幾個階段:

  • 下載
  • 安裝
  • 激活

下載

這是瀏覽器下載包含 Service Worker 的 .js 文件的時候。

安裝

要爲 web 應用程序安裝 Service Worker,必須先註冊它,這能夠在 JavaScript 代碼中完成。註冊 Service Worker 後,它會提示瀏覽器在後臺啓動 Service Worker 安裝步驟。

經過註冊 Service Worker,你能夠告訴瀏覽器你的 Service Worker 的 JavaScript 文件的位置。看看下面的代碼:

上例代碼首先檢查當前環境中是否支持 Service Worker API。若是支持,則 /sw.js 這個 Service Worker 就被註冊了。

每次頁面加載時均可以調用 register() 方法,瀏覽器會判斷 Service Worker 是否已經註冊,根據註冊狀況會對應的給出正確處理。

register() 方法的一個重要細節是 Service Worker 文件的位置。在本例中,能夠看到 Service Worker 文件位於域的根目錄,這意味着 Service Worker 範圍將是這個域下的。換句話說,這個 Service Worker 將爲這個域中的全部內容接收 fetch事件。若是咱們在 /example/sw.js 註冊 Service Worker 文件,那麼 Service Worker 只會看到以 /example/ 開頭的頁面的 fetch 事件(例如 /example/page1//example/page2/)。

一般在安裝步驟中,你須要緩存一些靜態資源。 若是全部文件都緩存成功,則 Service Worker 將被安裝。 若是任何文件沒法下載和緩存,則安裝步驟將失敗,Service Worker 將不會激活(即不會被安裝)。 若是發生這種狀況,不要擔憂,下次再試一次。 可是,這意味着若是它安裝,你知道你有這些靜態資源在緩存中。

若是註冊須要在加載事件以後發生,這就解答了你「註冊是否須要在加載事件以後發生」的疑惑。這不是必要的,但絕對是推薦的。

爲何?讓咱們考慮用戶第一次訪問你的 Web 應用程序。目前尚未 Service Worker,並且瀏覽器沒法預先知道最終是否會安裝 Service Worker。若是安裝了 Service Worker,瀏覽器將須要爲這個額外的線程花費額外的 CPU 和內存,不然瀏覽器將把這些額外的 CPU 和內存用於呈現 Web 頁面。

最重要的是,若是在頁面上安裝一個 Service Worker,就可能會有延遲加載和渲染的風險 —— 而不是儘快讓你的用戶可使用該頁面。

注意,這種狀況對第一次的訪問頁面時纔會有。後續的頁面訪問不會受到 Service Worker 安裝的影響。一旦 Service Worker 在第一次訪問頁面時被激活,它就能夠處理加載/緩存事件,以便後續訪問 Web 應用程序。這一切都是有意義的,由於它須要準備好處理受限的的網絡鏈接。

激活

安裝 Service Worker 以後,下一步將是激活它,這是處理舊緩存管理的好機會。

在激活步驟以後,Service Worker 將控制全部屬於其範圍的頁面,儘管第一次註冊 Service Worker 的頁面將不會被控制,直到再次加載。

Service Worker 一旦掌控,它將處於如下兩種狀態之一:

  • 處理從網頁發出網絡請求或消息時發生的提取和消息事件
  • Service Worker 將被終止以節省內存

Service Worker 生命週期以下:

Service Worker 安裝的內部機制

在頁面啓動註冊過程以後,看看 Service Worker 腳本中發生了什麼,它經過向 Service Worker 實例添加事件監聽來處理 install 事件:

如下是處理安裝事件時須要採起的步驟:

  • 開啓一個緩存
  • 緩存咱們的文件
  • 確認是否緩存了全部必需的資源

對於最基本的示例,你須要爲安裝事件定義回調並決定要緩存哪些文件。

self.addEventListener('install', function(event) { // Perform install steps });
複製代碼

下面是 Service Worker 簡單的一個內部安裝過程:

從上例代碼能夠獲得:

調用了caches.open() 和咱們想要的緩存名稱, 以後調用 cache.addAll() 並傳入文件數組。 這是一個promise 鏈( caches.open() 和 cache.addAll() )。 event.waitUntil() 方法接受一個承諾,並使用它來知道安裝須要多長時間,以及它是否成功。

若是成功緩存了全部文件,那麼將安裝 Service Worker。若是其中的一個文件下載失敗,那麼安裝步驟將失敗。這意味着須要當心在安裝步驟中決定要緩存的文件列表,定義一長串文件將增長一個文件可能沒法緩存的機會,致使你的 Service Worker 沒有獲得安裝。

處理 install 事件徹底是可選的,你能夠避免它,在這種狀況下,你不須要執行這裏的任何步驟。

運行時緩存請求

安裝了 Service Worker 後,用戶導航到另外一個頁面或刷新所在的頁面,Service Worker 將收到 fetch 事件。下面是一個例子,演示如何返回緩存的資源或執行一個新的請求,而後緩存結果:

上述流程:

  • 在這裏咱們定義了 fetch 事件,在 event.respondWith() 中,咱們傳遞了一個來自 caches.match()promise。 此方法查看請求,並查找來自 Service Worker 建立的任何緩存的任何緩存結果。
  • 若是在緩存中,響應內容就被恢復了。
  • 不然,將會執行 fetch。
  • 檢查狀態碼是否是 200,同時檢查響應類型是 basic,代表響應來自咱們最初的請求。在這種狀況下,不會緩存對第三方資源的請求。
  • 響應被緩存下來

若是經過檢查,克隆響應。這是由於響應是 Stream,因此只能消耗一次。既然要返回瀏覽器使用的響應,並將其傳遞給緩存使用,就須要克隆它,以即可以一個發送到瀏覽器,一個發送到緩存。

更新 Service Worker

當用戶訪問你的 Web 應用程序時,瀏覽器試圖從新下載包含 Service Worker 代碼的 .js 文件,這是在後臺完成的。

若是如今下載的 Service Worker 的文件與當前 Service Worker 的文件相好比果有一個字節及以上的差別,瀏覽器將假設 Service Worker 文件已改過,瀏覽器就會啓動新的 Service Worker。

新的 Service Worker 將啓動而且安裝事件將被移除。然而,在這一點上,舊的 Service Worker 仍在控制你的 web 應用的頁面,這意味着新的 Service Worker 將進入 waiting 狀態。

一旦你的 Web 應用程序當前打開的頁面被關閉,舊的 Service Worker 將被瀏覽器殺死,新 Service Worker 接管了控制權,它的激活事件將被激發

爲何須要這些?爲了不 Web 應用程序的兩個版本同時在不一樣的 tab 上運行的問題——這在 Web 上是很是常見的,而且可能會產生很是嚴重的bug(例如,在瀏覽器中本地存儲數據時使用不一樣的模式)。

從緩存中刪除數據

在激活回調中發生的一個常見任務是緩存管理。你要在激活回調中這樣作的緣由是,若是你要在安裝步驟中清除全部舊的緩存,任何保留全部當前頁面的舊 Service Worker 將會忽然中止服務來自該緩存的文件。

這裏提供了一個如何從緩存中刪除一些不在白名單中的文件的例子(在本例中,有 page-一、page-2 兩個實體):

要求 HTTPS 的緣由

在構建 Web 應用程序時,經過 localhost 使用 Service Workers,可是一旦將其部署到生產環境中,就須要準備好 HTTPS( 這是使用HTTPS 的最後一個緣由)。

使用 Service Worker,能夠很容易被劫持鏈接並僞造響應。若是不使用 HTTPs,人的web應用程序就容易受到黑客的攻擊。

爲了更安全,你須要在經過 HTTPS 提供的頁面上註冊 Service Worker,以便知道瀏覽器接收的 Service Worker 在經過網絡傳輸時未被修改。

瀏覽器支持

瀏覽器對 Service Worker 的支持正在變得愈來愈好:

Service Workers 特性將愈來愈完善及強大

Service Workers 提供的一些獨特特性包括:

  • 推送通知 — 容許用戶選擇從網絡應用程序及時更新。
  • 後臺同步 — 容許延遲操做,直到用戶具備穩定的鏈接。經過這種方式,能夠確保用戶想發送的任何內容實均可以發送。
  • 按期同步(後續開放) — 提供管理按期後臺同步功能的 API。
  • Geofencing (後續開放) — 能夠定義參數,也稱爲圍繞感興趣領域的 geofences。當設備經過geofence 時,Web 應用程序會收到一個通知,該通知容許根據用戶的地理位置提供更好的體驗。

原文:

blog.sessionstack.com...

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

你的點贊是我持續分享好東西的動力,歡迎點贊!

一個笨笨的碼農,個人世界只能終身學習!

更多內容請關注公衆號《大遷世界》!

關於Fundebug

Fundebug專一於JavaScript、微信小程序、微信小遊戲、支付寶小程序、React Native、Node.js和Java線上應用實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了9億+錯誤事件,付費客戶有Google、360、金山軟件、百姓網等衆多品牌企業。歡迎你們免費試用

相關文章
相關標籤/搜索