你是否曾經因為網路不穩定而苦惱?是否希望你的網頁在離線時依然能流暢執行?今天,我們將探討如何利用 Workbox 來最佳化你的 Service Worker,提升網頁效能,確保你的 Web 應用在任何環境下都能穩定執行。
目前您可能還用不到這篇文章,不過可以先收藏起來。希望將來它能為您提供所需的幫助!
🎈什麼是 Service Worker?
在深入瞭解 Workbox 之前,瞭解 Service Worker 的基礎知識是必要的。Service Worker是執行在瀏覽器背後的獨立執行緒,用於攔截和處理網路請求、管理快取和處理推送通知。它的主要目的是增強 Web 應用的離線體驗和效能。
Service Worker 在使用者訪問網頁時被安裝,並在後臺執行,能夠在不干擾主頁面的情況下執行任務。
Service Worker 的生命週期分為以下3個階段:
1、安裝(Install):當瀏覽器發現新的 Service Worker 指令碼時,會觸發 install
事件。在這個階段,開發者通常會快取應用的靜態資源。
self.addEventListener('install', event => { event.waitUntil( caches.open('my-cache').then(cache => { return cache.addAll([ '/', '/index.html', '/styles.css', '/script.js' ]); }) ); });
2、啟用(Activate):安裝完成後,Service Worker 會進入啟用階段。在這個階段,開發者可以清理舊的快取,確保新的快取策略生效。
self.addEventListener('activate', event => { event.waitUntil( caches.keys().then(cacheNames => { return Promise.all( cacheNames.map(cacheName => { if (cacheName !== 'my-cache') { return caches.delete(cacheName); } }) ); }) ); });
3、執行(Running):啟用後,Service Worker 進入執行狀態,開始攔截和處理網路請求。開發者可以透過 fetch
事件來控制請求的處理方式。
self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request).then(response => { return response || fetch(event.request); }) ); });
Service Worker主要應用於以下幾個場景:
離線支援:透過快取靜態資源和動態內容,確保應用在沒有網路連線時仍然可以使用。
快取管理:提高應用效能,透過快取減少網路請求次數和加快頁面載入速度。
推送通知:Service Worker 可以處理推送通知,即使使用者沒有開啟應用也能接收訊息。
手動編寫 Service Worker 也可以實現,但是過於複雜,現在有一款比較成熟 npm 庫 Workbox。
為什麼選擇 Workbox?🔥🔥
Workbox 功能強大特性
Workbox 是由 Google 開發的一組庫和工具,幫助開發者輕鬆地將 Service Worker 整合到他們的 Web 應用中。它簡化了快取管理和離線支援,使得 Web 應用能夠在沒有網路連線的情況下依然保持高效能和可靠性。
主要用途包括:
簡化快取管理:透過預定義的策略自動處理資源的快取。
提高效能:加快資源載入速度,減少伺服器負載。
增強離線功能:確保應用在離線狀態下仍能正常執行。
提供外掛與擴充套件:透過各種外掛輕鬆擴充套件功能,如背景同步、Google Analytics整合等。
與手動編寫 Service Worker 的對比,使用 Workbox,開發者只需配置即可,大大提升了開發效率。經過廣泛測試和社羣驗證,提供了高可靠性和效能最佳化的預設實現。
引入 Workbox(最簡單的方法)
引入 Workbox(最簡單的方法)可以透過以下幾個步驟完成。Workbox 是一個強大的庫,用於幫助開發人員簡化構建程序中的離線支援和快取策略。以下是最簡單的方法來引入 Workbox:
1. 使用 Workbox CLI
Workbox CLI 是最快速且簡單的方式來引入 Workbox 並生成 Service Worker 檔案。
安裝 Workbox CLI
你需要全域性安裝 Workbox CLI 工具。開啟終端並執行以下命令:
npm install -g workbox-cli
初始化 Workbox
在你的專案根目錄下,執行以下命令來初始化 Workbox:
workbox wizard
這會引導你完成配置過程,並生成一個
workbox-config.js
檔案。生成 Service Worker
執行以下命令生成 Service Worker 檔案:
workbox generateSW workbox-config.js
這將建立一個
service-worker.js
檔案,你需要將它註冊到你的應用中。註冊 Service Worker
在你的應用入口檔案(例如
index.js
或main.js
)中新增以下程式碼來註冊 Service Worker:if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js').then(registration => { console.log('SW registered: ', registration); }).catch(registrationError => { console.log('SW registration failed: ', registrationError); }); }); }
2. 使用 Workbox CDN
如果你不想使用 CLI 工具,你也可以直接透過 CDN 引入 Workbox:
在 HTML 檔案中新增 Workbox 的 CDN 連結
在你的 HTML 檔案的
<head>
標籤中新增以下程式碼:<script src="https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js"></script>
建立和註冊 Service Worker
建立一個
service-worker.js
檔案並新增以下程式碼:importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'); workbox.precaching.precacheAndRoute(self.__WB_MANIFEST);
然後在你的應用入口檔案中註冊這個 Service Worker:
if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js').then(registration => { console.log('SW registered: ', registration); }).catch(registrationError => { console.log('SW registration failed: ', registrationError); }); }); }
使用 Workbox 外掛(可選)
你可以根據需要新增其他 Workbox 外掛,例如快取策略:
workbox.routing.registerRoute( ({request}) => request.destination === 'image', new workbox.strategies.CacheFirst({ cacheName: 'images', plugins: [ new workbox.expiration.ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 30 * 24 * 60 * 60, // 30 天 }), ], }) );
Workbox配置
Workbox 預快取功能
workbox.precaching
物件提供了常用的預快取功能,其中最常用的方法是 workbox.precaching.precacheAndRoute
。它的作用跟我們前面實現的 Precacher.precacheAndRoute()
的功能類似, 都是將傳入的資源列表進行預快取,同時對匹配到的預快取請求直接從本地快取中讀取並返回。
workbox.routing.precacheAndRoute([ { url: '/index.html', revision: 'asdf' }, '/index.abc.js', '/index.bcd.css' ])
Workbox 路由功能全面解析
Workbox 對資源請求匹配和對應的快取策略執行進行了統一管理,採用路由註冊的組織形式,以此來規範化動態快取。Workbox 提供了簡潔的 workbox.routing.registerRoute
方法來註冊路由,規範化動態快取操作。基本用法如下:
workbox.routing.registerRoute(match, handlerCb)
🐱路由匹配規則詳解
workbox.routing.registerRoute
的第一個引數 match
是路由匹配規則,支援以下幾種匹配模式:
字串匹配:對資源 URL 進行字串匹配。無論是完整 URL 還是相對路徑,都可以匹配到相應資源。
workbox.routing.registerRoute('http://127.0.0.1:8080/index.css', handlerCb) workbox.routing.registerRoute('/index.css', handlerCb) workbox.routing.registerRoute('./index.css', handlerCb)
例如,以上註冊的路由都能匹配到 http://127.0.0.1:8080/index.css
。
正則匹配:對資源 URL 進行正則匹配。
workbox.routing.registerRoute(//index.css$/, handlerCb)
這個規則可以匹配以下同域資源:
http://127.0.0.1:8080/index.css
http://127.0.0.1:8080/a/index.css
但無法匹配跨域資源。為匹配跨域資源需明確指定域名:
workbox.routing.registerRoute( /^https://third-party-site.com/.*/index.css$/, handlerCb )
自定義方法匹配:根據需求實現複雜的資源請求匹配規則。
const match = ({url, event}) => { return url.pathname === '/index.html' }
match
方法接收 url
和 event
引數,其中 url
是 URL
類例項,event
是 fetch
事件回撥引數。
🐱資源請求處理方法
第二個引數 handlerCb
決定如何響應匹配到的請求,可以從網路、快取獲取資源或在 Service Worker 中直接生成響應。
const handlerCb = ({url, event, params}) => { return Promise.resolve(new Response('Hello World!')) }
handlerCb
方法接收的物件包含以下屬性:
url
:經過URL
類例項化的event.request.url
。event
:fetch
事件回撥引數。params
:自定義匹配方法返回的值。
注意:handlerCb
必須是非同步函式,返回一個 Promise,該 Promise 的解析結果必須是一個 Response 物件。
Workbox 的路由功能透過統一管理資源請求匹配和快取策略,顯著提升了前端開發的效率和使用者體驗。
Workbox快取策略(🔥🔥核心點,非常重要)
Workbox 提供了一系列靈活且強大的快取策略,幫助開發者最佳化Web應用的效能。以下是幾種常用的快取策略以及它們的詳細說明和應用場景:
NetworkFirst:網路優先
CacheFirst:快取優先
NetworkOnly:僅使用正常的網路請求
CacheOnly:僅使用快取中的資源
StaleWhileRevalidate:從快取中讀取資源的同時傳送網路請求更新本地快取
const {NetworkFirst, CacheFirst, StaleWhileRevalidate} = workbox.strategies; workbox.routing.registerRoute(/\api/, new workbox.strategies.NetworkFirst())
Stale-while-revalidate
當請求的路由有對應的 Cache 快取結果就直接返回,在返回 Cache 快取結果的同時會在後臺發起網路請求拿到請求結果並更新 Cache 快取,如果本來就沒有 Cache 快取的話,直接就發起網路請求並返回結果,這對使用者來說是一種非常安全的策略。
在第一次請求獲取資源時,從網路中提取資源,將其放入快取中並返回網路響應。
對於後續請求,首先從快取提供資源,然後“在後臺”從網路重新請求該資源,並更新資源的快取條目。
對於此後的請求,您將收到在上一步中從快取中放置的最後一個網路提取的版本。
Cache First
當匹配到請求之後直接從 Cache 快取中取得結果,如果 Cache 快取中沒有結果,那就會發起網路請求,拿到網路請求結果並將結果更新至 Cache 快取,並將結果返回給客戶端。這種策略比較適合結果不怎麼變動且對實時性要求不高的請求。
Network First
優先嚐試拿到網路請求的返回結果,如果拿到網路請求的結果,就將結果返回給客戶端並且寫入 Cache 快取,如果網路請求失敗,那最後被快取的 Cache 快取結果就會被返回到客戶端,這種策略一般適用於返回結果不太固定或對實時性有要求的請求,為網路請求失敗進行兜底。
Cache Only
始終從快取中獲取資源,不發起網路請求。
Network Only
始終從網路請求資源,不使用快取。
擴充套件延伸:Workbox自定義策略
在某些情況下,您可能希望使用自己的其他策略來響應請求,或者只是透過模板在 Service Worker 中生成請求。
為此可以提供一個非同步返回 Response
物件的函式 handler
。
const handler = async ({ url, event }) => { return new Response(`Custom handler response.`); }; workbox.routing.registerRoute(new RegExp(matchString), handler);
需要注意的是,如果在 match
回撥中返回一個值,它將 handler
作為 params
引數傳遞到回撥中。
const match = ({ url, event }) => { if (url.pathname === '/example') { return { name: 'Workbox', type: 'guide', }; } }; const handler = async ({ url, event, params }) => { // Response will be "A guide to Workbox" return new Response(`A ${params.type} to ${params.name}`); }; workbox.routing.registerRoute(match, handler);
如果 URL 中的某些資訊可以在 match 回撥中解析一次並在中使用,則這可能會對 handler
有所幫助。
總結
希望這篇文章對你理解使用 Workbox 功能有所幫助。如果你有任何疑問或見解,歡迎在評論區分享或提問,讓我們共同進步!