當前位置:
首頁 > 科技 > 【第1025期】理解Service Worker

【第1025期】理解Service Worker

前言

昨天推送完看了會綜藝節目就順便去環島路跑步,上一次跑應該是去年的事情了。今日早讀文章由百度外賣前端@安秦翻譯分享。

正文從這開始~

譯者注

PWA是最近前端最火熱的一個概念之一,Service Worker為PWA賦能離線可用性以及push消息。

原文最後講了在Ember.js框架上的實踐介紹,因為原作者是Ember.js的擁躉,但鑒於國內React、Vue、Angular居多(不要引起戰爭,害怕.jpg),譯文就省略那部分內容了。

Service Worker是啥?能用來幹啥?又如何能提升你的web應用的體驗?本文就是來回答這些問題的。

背景

在那個網路還很年輕的時代,很少有人去想一個網頁在用戶斷網的情況下應該有什麼樣的表現。你就應該一直是在線的。

然而在移動互聯網的時代,不穩定的網路鏈接在現代網路變得原來越常見。鑒於此,允許網站自己決定離線時的行為變得彌足珍貴,這樣用戶就不會被網路狀態局限。

最初,H5標準中推出了應用緩存作為離線web應用的解決方案。它以一個緩存清單為中心將HTML與JS組合起來,這清單是一個用聲明式語法編寫的配置文件。

但是最終,大家發現應用緩存存在太多的坑。此後,稍有人再贊同使用它,取而代之的是Service Worker。

Service Worker帶來的離線可用解決方案更加符合未來發展趨勢。它摒棄了應用緩存聲明式的設計,改用一種更加命令式或者說程序性的設計方案。

Service Worker是一種在瀏覽器環境當中於一個持久的背景進程當中執行代碼的方法。被執行的代碼時事件驅動的,也就是說驅動一個Service Worker的行為的,是在其中產生的事件。

本文後續就是簡要地介紹一下那些事件。然而想要開始利用Service Worker,你需要先實現你的web應用明面上的功能,然後再於其中註冊Service Worker。

註冊

下方的代碼描繪了如何在瀏覽器客戶端當中註冊你的Service Worker。這是通過在web應用的某處調用 register 實現的:

if(navigator.serviceWorker){

navigator.serviceWorker.register( /sw.js )

.then(registration=>{

console.log( 恭喜。作用範圍: ,registration.scope);

})

.catch(error=>{

console.log( 抱歉 ,error);

});

}

這就告知瀏覽器從哪裡能找到你實現的Service Worker。瀏覽器會找到 /sw.js 文件,然後保存在當前被訪問的域名的名下。該文件包含各類事件的處理邏輯,整體定義你的Service Worker 的行為。

在Chrome開發者工具中查看一個被註冊的Service Worker

上面的代碼還會定義你的Service Worker的作用範圍。文件路徑 /sw.js 暗含默認情況下你的SW的作用範圍是你的URL的根目錄(比如 http://localhost:3000/ )。那麼這樣,你的SW里能通過監聽事件獲知所有在你的url根目錄里發生的請求。一個如 /js/sw.js 這樣的路徑只會捕獲到 http://localhost:3000/js 下的請求。

你也可以顯式地定義SW的作用範圍,只要給 register 函數傳第二個參數:

navigator.serviceWorker.register( /sw.js ,{scope: /js })

事件處理

現在你的Service Worker已經註冊好了,就該輪到實現事件處理邏輯,監聽Service Worker生命周期當中的各種事件。

Install事件

Install事件是在你的Service Worker第一次註冊以及SW文件(/sw.js)發生變化的時候觸發的(瀏覽器會自動鑒別是否發生改變了)。

利用安裝事件,可以實現你的SW初始化邏輯,或者說通過只執行一次的命令來設定你的SW初始狀態。一種常見的用法是在安裝階段提權準備好緩存。

以下就是是一個在安裝階段預先緩存資源的例子:

constCACHE_NAME= cache-v1 ;

consturlsToCache=[

/ ,

/js/main.js ,

/css/style.css ,

/img/bob-ross.jpg ,

];

self.addEventListener( install ,event=>{

caches.open(CACHE_NAME)

.then(cache=>{

returncache.addAll(urlsToCache);

});

});

urlsToCache 所包含的就是我們想要提前緩存的url列表。

caches 是一個全局 CacheStorage 對象,用於管理瀏覽器緩存。我們通過調用 open 來獲取一個可操作的具體 Cache 對象。

cache.addAll 接收一個url數組,對每一個進行請求,然後將響應結果存到緩存里。它以請求的詳細信息為鍵來緩存每一個值。閱讀 addAll 文檔了解更多。

在Chrome開發者工具里查看緩存數據

Fetch事件

每當網頁里產生一個網路請求,都會觸發一個fetch事件。觸發的時候,你的SW可以「攔截」請求並決定想要返回什麼——是緩存的數據還是一個實際網路請求的結果。

以下的例子演示一個緩存優先策略:任何匹配請求的緩存數據都會優先發送,不會發出網路請求。只有當找不到存在的緩存數據時,才會產生一個網路請求。

self.addEventListener( fetch ,event=>{

const{request}=event;

constfindResponsePromise=caches.open(CACHE_NAME)

.then(cache=>cache.match(request))

.then(response=>{

if(response){

returnresponse;

}

returnfetch(request);

});

event.respondWith(findResponsePromise);

});

request 存在於一個 FetchEvent 對象,包含請求的詳情。它可以用來查找一個匹配的緩存響應結果。

cache.match 會嘗試為一個請求尋找匹配的緩存值。如果沒能找到,這個 promise 會得到 undefined 結果。我們會檢查到這種情況,並且如果發生了,就調用一次 fetch 來產生網路請求。

event.respondWith 是一個 FetchEvent 對象里專門用於向瀏覽器發送響應結果的方法。它接受一個最終能解析成網路響應的 promise。

緊接著,調用 event.waitUntil 來在SW被終止前執行一個 Promise 非同步流程。在這裡我們先做一個網路請求然後再將其緩存。這個非同步操作完成後,waitUntil才會解析完成,整個操作才可以終止。

Activate事件

這個事件的文檔相較而言比較少,但對於你更新SW文件很有幫助,你可以在升級SW文件的時候針對之前的版本執行清理或其他維護操作。

當你更新你的SW文件(/sw.js),瀏覽器會檢測到並在開發者工具中如下展示:

你的新Service Worker是「等待激活」狀態

當實際的網頁關掉並重新打開時,瀏覽器會將原先的Service Worker替換成新的,然後在 install 事件之後觸發 activate 事件。如果你需要清理緩存或者針對原來的SW執行維護性操作,activate 事件就是做這些事情的絕佳時機。

Sync事件

Sync事件讓你可以先將網路相關任務延遲到用戶有網路的時候再執行。這個功能常被稱作「背景同步」。這功能可以用於保證任何用戶在離線的時候所產生對於網路有依賴的操作,最終可以在網路再次可用的時候抵達它們的目標。

一下是一個背景同步樣例。你需要你的前台JS註冊一個同步事件,同時在SW里實現sync事件監聽處理:

// app.js

navigator.serviceWorker.ready

.then(registration=>{

document.getElementById( submit ).addEventListener( click ,()=>{

registration.sync.register( submit ).then(()=>{

console.log( sync registered! );

});

});

});

這裡,我們指定在一個按鈕的點擊事件里,在一個全局的 ServiceWorkerRegistration 對象身上調用 sync.register。這裡,我們指定在一個按鈕的點擊事件里,在一個全局的 ServiceWorkerRegistration 對象身上調用 sync.register。

簡單地講,任何你需要確保在有網路時立刻執行或者等到有網再執行的操作,都需要註冊為一個sync事件。

這操作可以是發送一個評論,或者獲取用戶信息,在SW的事件監聽器里會如下定義:

// sw.js

self.addEventListener( sync ,event=>{

if(event.tag=== submit ){

console.log( sync! );

}

});

這裡,我們監聽一個 sync 事件,然後在 SyncEvent 對象上檢查 tag 是否匹配我們在點擊事件里所設定的 submit 。

如果多個 tag 標記為 submit 的 sync事件被註冊了,sync 事件處理器只會運行一次。

所以在這個例子里,如果用戶離線了,然後點擊按鈕7次,當網路再次連上,所有的sync註冊都會合而為一,sync事件只會觸發一次。

如果你希望每一次點擊都能觸發 sync 事件,你就需要在註冊的時候賦予它們不同的tag。

Sync事件是什麼時候觸發的?

如果用戶的網路時聯通的,那麼sync事件會立刻觸發並且立刻執行你所定義的任務。

而如果用戶離線了,sync 事件會在網路恢復後第一時間觸發。

如果你想我一樣,想要在Chrome里體驗這個功能,你需要真實地斷開你的網路,禁用一下Wi-Fi或者關閉一下網路驅動器。只是在Chrome開發者工具的Network選項卡里模擬網路斷開是不會觸發 sync 事件的。

欲了解更多,可以閱讀這篇解釋文檔,以及這篇對背景同步的介紹。不過要注意,sync事件還沒有在瀏覽器中得到普及(在寫下這篇文章的時候還只有Chrome支持),並且用法在未來還可能有變化,請保持關注。

Push消息

在Service Worker里,通過 push 事件以及瀏覽器的 Push API,可以實現push消息的功能。

在說道web push消息的時候,其實涉及到兩個正在完善中的技術:消息提醒 與 信息推送。

消息提醒

用Service Worker實現消息提醒挺簡單直接:

// app.js

// ask for permission

Notification.requestPermission(permission=>{

console.log( permission: ,permission);

});

// display notification

functiondisplayNotification(){

if(Notification.permission== granted ){

navigator.serviceWorker.getRegistration()

.then(registration=>{

registration.showNotification( this is a notification! );

});

}

}

// sw.js

self.addEventListener( notificationclick ,event=>{

// 消息提醒被點擊的事件

});

self.addEventListener( notificationclose ,event=>{

// 消息提醒被關閉的事件

});

你需要先向用戶尋求讓你的網頁產生消息提醒的許可權。之後,你就可以彈出提示信息,然後處理某些事件,比如用戶把消息關掉的事件。

信息推送

信息推送涉及到利用瀏覽器提供的Push API以及後端的配合實現。要講解如何使用Push API完全可以再寫一篇文章,不過基本的套路如下:

這是個略微複雜難懂的過程,已經超出這篇文章的討論範圍。不過如果你很感興趣,可以閱讀這篇push消息介紹。

結語

希望你對Service Workers以及它的基礎結構已經得到了更加清晰的理解,並且了解到web應用可以如何利用它來增強用戶體驗。

關於本文

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 前端早讀課 的精彩文章:

你與阿里雲就差一份簡歷?撩P6/P7前端工程師
【第1023期】PostCSS介紹
聊一聊前端自動化測試(上)
聊一聊前端自動化測試(下)
如果你的產品停止成長,你該怎麼做?

TAG:前端早讀課 |

您可能感興趣

「Red Velvet」「盤點」181025 概念富人RedVelvet 各成員最絕配的概念盤點
181025 喜大普奔!吳亦凡《悟》榮登Billboard中國榜第一
「Infinite」「新聞」181025 明洙出席電影試映會 360°無死角美男
「BTOB」「分享」181025 「Idol Radio」勛D戴黃色帽子 這可愛程度可不是開玩笑的
「EXO」「新聞」181025 爆炸頭一樣hold住!XIUMIN五輯預告照叛逆來襲
「TFBOYS」「新聞」181025 凱Boss受邀出席2018時裝之夜,以新生力量碰撞時代主流
「Apink」「新聞」181025 惡童三兄妹 耀眼帥氣的外貌
1025不僅僅Note8發布,魅族16th還有現貨!
「EXO」「新聞」181025 說到南韓完顏團,iKON成員脫口而出「EXO」
「TWICE」「分享」181025 轉學生T寶來報道了!TWICE今日下午進行「認哥」錄製
寶格麗OCTO系列102581 BGO41BBSVD腕錶男士手錶推薦
拯救你的爛照片 魅族Note8 1025攜黑科技而來
搭驍龍632拍照有驚喜 魅族Note8 1025見
181025 吳亦凡的太空夢你了解嗎 galaxy王子誠邀每個你述說太空夢
181025 凱Boss受邀出席2018時裝之夜 以新生力量碰撞時代主流
「EXO」「分享」181025 同是嗅花香,伯賢一人演繹暖男哥哥&叛逆弟弟
6英寸+64G+4100mAh,這款超級快充手機現在僅售1025元!
【每日說明書 , 第1025期】ALLIE 皚麗 控油防晒妝前乳 (玫紅色)
僅售1025元的大屏手機,網友:我還是買小米Max2吧
千元機人氣王:1025的紅米Note5值不值得買?看完你就知道