服務工作者的其中一個功能,是在服務工作者安裝時,將一組檔案儲存至快取。這通常稱為「預先快取」,因為您是在使用 Service Worker 之前快取內容。
這樣做的主要原因是讓開發人員可以控管快取,也就是說,他們可以決定檔案快取的時間和時間長度,並且在不連上網路的情況下,將檔案提供給瀏覽器,也就是說,他們可以用來建立可離線運作的網頁應用程式。
Workbox 會簡化 API 並確保資產能有效下載,因此可代您處理預先快取的繁重工作。
workbox-precaching 的運作方式
第一次載入網頁應用程式時,workbox-precaching
會查看您要下載的所有素材資源,移除任何重複項目,並連結相關的服務工作者事件,以便下載及儲存素材資源。已包含版本資訊 (例如內容雜湊) 的網址可用做為快取金鑰,無須進一步修改。不含版本資訊的網址會在快取鍵中附加額外的網址查詢參數,代表 Workbox 在建構期間產生的內容雜湊。
workbox-precaching
會在服務工作者的 install
事件期間執行所有這些操作。
當使用者日後再次造訪您的網路應用程式,且您有使用不同的預先快取素材資源的新服務工作者時,workbox-precaching
會查看新清單,並根據修訂版本判斷哪些素材資源是全新的,以及哪些現有素材資源需要更新。任何新的素材資源或更新修訂版,都會在新的服務工作者 install
事件期間加入快取。
只有在 activate
事件觸發時,這個新的服務工作者才會用來回應要求。workbox-precaching
會在 activate
事件中檢查目前網址清單中是否有不再存在的快取素材資源,並從快取中移除這些素材資源。
workbox-precaching
會在每次安裝及啟用服務工作者時執行這些步驟,確保使用者擁有最新的素材資源,並只下載已變更的檔案。
提供預先快取的回應
呼叫 precacheAndRoute()
或 addRoute()
會建立與預先快取網址要求相符的路徑。
這個路徑採用的回應策略是「先快取」:系統會使用預先快取的回應,除非該快取回應不存在 (因某些意外錯誤導致),否則會改用網路回應。
呼叫 precacheAndRoute()
或 addRoute()
的順序十分重要。通常,您會在服務工作者檔案的早期呼叫此方法,然後再透過 registerRoute()
註冊任何其他路徑。如果您先呼叫 registerRoute()
,且該路徑與傳入的請求相符,系統會使用您在該額外路徑中定義的策略回應,而非 workbox-precaching
使用的快取優先策略。
預先快取清單的說明
workbox-precaching
預期物件陣列含有 url
和 revision
屬性。這個陣列有時也稱為預快取資訊清單:
import {precacheAndRoute} from 'workbox-precaching';
precacheAndRoute([
{url: '/index.html', revision: '383676'},
{url: '/styles/app.0c9a31.css', revision: null},
{url: '/scripts/app.0d5770.js', revision: null},
// ... other entries ...
]);
這個清單會參照一組網址,每個網址都有各自的「修訂」資訊。
在上述範例中的第二個和第三個物件中,revision
屬性設為 null
。這是因為修訂資訊位於網址本身,這通常是靜態資產的最佳做法。
第一個物件 (/index.html
) 會明確設定修訂版本屬性,這是檔案內容的自動產生雜湊。與 JavaScript 和 CSS 資源不同,HTML 檔案通常無法在網址中加入修訂資訊,否則網頁內容一有變動,網站上的這些檔案連結就會中斷。
透過將修訂版本屬性傳遞至 precacheAndRoute()
,Workbox 就能得知檔案何時變更,並據此更新檔案。
Workbox 提供的工具可協助您產生這份清單:
workbox-build
:這是可用於 gulp 工作或做為 npm 執行指令碼的節點套件。workbox-webpack-plugin
:webpack 使用者可以使用這個外掛程式。workbox-cli
:我們的 CLI 也可用來產生資產清單,並將這些資產新增至服務工作者。
預先快取檔案的傳入要求
workbox-precaching
會預設執行的其中一項操作,是操控傳入的網路要求,嘗試比對已快取的檔案。這可滿足網路上的常見做法。
舉例來說,/
的要求通常可以由 /index.html
中的檔案滿足。
以下是 workbox-precaching
預設執行的操控項目清單,以及如何變更該行為。
忽略網址參數
您可以變更含有搜尋參數的要求,移除特定值或移除所有值。
根據預設,系統會移除以 utm_
開頭或完全比對 fbclid
的搜尋參數,這表示系統會使用 /about.html
的快取項目來滿足對 /about.html?utm_campaign=abcd
的要求。
您可以使用 ignoreURLParametersMatching
忽略不同的搜尋參數組合:
import {precacheAndRoute} from 'workbox-precaching';
precacheAndRoute(
[
{url: '/index.html', revision: '383676'},
{url: '/styles/app.0c9a31.css', revision: null},
{url: '/scripts/app.0d5770.js', revision: null},
],
{
// Ignore all URL parameters.
ignoreURLParametersMatching: [/.*/],
}
);
目錄索引
結尾為 /
的要求,預設會與結尾附加 index.html
的項目進行比對。這表示 /
的傳入要求可透過預先快取的項目 /index.html
自動處理。
您可以將這項設定改為其他值,或完全停用,方法是設定 directoryIndex
:
import {precacheAndRoute} from 'workbox-precaching';
precacheAndRoute(
[
{url: '/index.html', revision: '383676'},
{url: '/styles/app.0c9a31.css', revision: null},
{url: '/scripts/app.0d5770.js', revision: null},
],
{
directoryIndex: null,
}
);
簡潔網址
如果要求無法與預先快取內容相符,我們會在結尾處新增 .html
,以支援「清晰」網址 (又稱為「漂亮」網址)。這表示 /about
這類要求會由 /about.html
的預快取項目處理。
您可以設定 cleanUrls
來停用此行為:
import {precacheAndRoute} from 'workbox-precaching';
precacheAndRoute([{url: '/about.html', revision: 'b79cd4'}], {
cleanUrls: false,
});
自訂操控
如果您想定義從傳入要求到預先快取素材資源的自訂配對,可以使用 urlManipulation
選項。這應該是回呼,會傳回可能相符項目的陣列。
import {precacheAndRoute} from 'workbox-precaching';
precacheAndRoute(
[
{url: '/index.html', revision: '383676'},
{url: '/styles/app.0c9a31.css', revision: null},
{url: '/scripts/app.0d5770.js', revision: null},
],
{
urlManipulation: ({url}) => {
// Your logic goes here...
return [alteredUrlOption1, alteredUrlOption2];
},
}
);
進階用途
直接使用 PrecacheController
根據預設,workbox-precaching
會為您設定 install
和 activate
事件監聽器。如果您需要更多控制權,對於熟悉 Service Worker 的開發人員來說,這可能不是理想做法。
您可以直接使用 PrecacheController
來新增項目至預先快取,並決定這些資產的安裝時間和清除時間,而非使用預設匯出項目。
import {PrecacheController} from 'workbox-precaching';
const precacheController = new PrecacheController();
precacheController.addToCacheList([
{url: '/styles/example-1.abcd.css', revision: null},
{url: '/styles/example-2.1234.css', revision: null},
{url: '/scripts/example-1.abcd.js', revision: null},
{url: '/scripts/example-2.1234.js', revision: null},
]);
precacheController.addToCacheList([{
url: '/index.html',
revision: 'abcd',
}, {
url: '/about.html',
revision: '1234',
}]);
self.addEventListener('install', (event) => {
// Passing in event is required in Workbox v6+
event.waitUntil(precacheController.install(event));
});
self.addEventListener('activate', (event) => {
// Passing in event is required in Workbox v6+
event.waitUntil(precacheController.activate(event));
});
self.addEventListener('fetch', (event) => {
const cacheKey = precacheController.getCacheKeyForURL(event.request.url);
event.respondWith(caches.match(cacheKey).then(...));
});
直接讀取預先快取的素材資源
有時您可能需要直接讀取預先快取的素材資源,而非在 workbox-precaching
可自動執行的路徑設定之外。舉例來說,您可能會想預先快取部分 HTML 範本,然後在建構完整回應時擷取並使用這些範本。
一般來說,您可以使用 Cache Storage API 取得預先快取的 Response
物件,但有一個小問題:呼叫 cache.match()
時需要使用的網址快取鍵可能包含 workbox-precaching
自動建立及維護的版本控制參數。
如要取得正確的快取索引鍵,您可以呼叫 getCacheKeyForURL()
,傳入原始網址,然後使用結果對適當的快取執行 cache.match()
。
import {cacheNames} from 'workbox-core';
import {getCacheKeyForURL} from 'workbox-precaching';
const cache = await caches.open(cacheNames.precache);
const response = await cache.match(getCacheKeyForURL('/precached-file.html'));
或者,如果您只需要預先快取的 Response
物件,可以呼叫 matchPrecache()
,系統會自動使用正確的快取索引鍵,並在正確的快取中搜尋:
import {matchPrecache} from 'workbox-precaching';
const response = await matchPrecache('/precached-file.html');
清除舊的預先快取
大多數 Workbox 版本都會維持相同的格式來儲存預快取資料,舊版 Workbox 建立的預快取資料通常可由新版版本直接使用。不過,預先快取儲存空間偶爾會發生重大變更,導致現有使用者必須重新下載所有內容,並使先前預先快取的資料失效。(Workbox v3 和 v4 版本之間發生了這種變更)。
這類過時的資料不應影響正常運作,但會影響整體儲存空間配額用量,因此建議您明確刪除這類資料,以免造成使用者困擾。方法是將 cleanupOutdatedCaches()
新增至服務工作者,或是設定 cleanupOutdatedCaches: true
(如果您使用 Workbox 的建構工具產生服務工作者)。
使用子資源完整性
有些開發人員可能希望在從網路擷取先前快取的網址時,能透過子資源完整性強制執行額外保證。
您可以將名為 integrity
的額外選用屬性新增至預先快取資訊清單中的任何項目。如果提供此值,系統會在建構用於填入快取的 Request
時,將其用作 integrity
值。如果不一致,預先快取程序就會失敗。
決定哪些預先快取資訊清單項目應具有 integrity
屬性,以及找出要使用的適當值,都超出 Workbox 建構工具的範圍。相反地,如果開發人員想選擇採用這項功能,則應修改 Workbox 產生的預先快取資訊清單,自行加入適當的資訊。Workbox 的建構工具設定中的 manifestTransform
選項可協助您:
const ssri = require('ssri');
const integrityManifestTransform = (originalManifest, compilation) => {
const warnings = [];
const manifest = originalManifest.map(entry => {
// If some criteria match:
if (entry.url.startsWith('...')) {
// This has to be a synchronous function call, for example:
// compilation will be set when using workbox-webpack-plugin.
// When using workbox-build directly, you can read the file's
// contents from disk using, e.g., the fs module.
const asset = compilation.getAsset(entry.url);
entry.integrity = ssri.fromData(asset.source.source()).toString();
// Push a message to warnings if needed.
}
return entry;
});
return {warnings, manifest};
};
// Then add manifestTransform: [integrityManifestTransform]
// to your Workbox build configuration.
類型
CleanupResult
屬性
-
deletedCacheRequests
string[]
InstallResult
屬性
-
notUpdatedURLs
string[]
-
updatedURLs
string[]
PrecacheController
有效率地預先快取素材資源。
屬性
-
建構函式
void
建立新的 PrecacheController。
constructor
函式如下所示:(options?: PrecacheControllerOptions) => {...}
-
選項
PrecacheControllerOptions 選用
-
returns
-
-
策略
策略
-
啟用
void
刪除目前預先快取資訊清單中不再存在的素材資源。在服務工作者啟用事件中呼叫此方法。
注意:這個方法會為您呼叫
event.waitUntil()
,因此您不需要在事件處理常式中自行呼叫。activate
函式如下所示:(event: ExtendableEvent) => {...}
-
活動
ExtendableEvent
-
returns
Promise<CleanupResult>
-
-
addToCacheList
void
這個方法會將項目新增至預先快取清單,移除重複項目,並確保資訊有效。
addToCacheList
函式如下所示:(entries: (string | PrecacheEntry)[]) => {...}
-
項目
(string | PrecacheEntry)[]
要預先快取的項目陣列。
-
-
createHandlerBoundToURL
void
傳回函式,該函式會在預先快取中查詢
url
(考量帳戶修訂資訊),並傳回對應的Response
。createHandlerBoundToURL
函式如下所示:(url: string) => {...}
-
網址
字串
預先快取的網址,用於查詢
Response
。
-
returns
-
-
getCacheKeyForURL
void
傳回用於儲存特定網址的快取鍵。如果該網址未經過版本化,例如 `/index.html',則快取金鑰會是原始網址,並附加搜尋參數。
getCacheKeyForURL
函式如下所示:(url: string) => {...}
-
網址
字串
您要查詢快取索引鍵的網址。
-
returns
字串
與原始網址的快取索引鍵相對應的版本網址,如果該網址未預先快取,則為未定義。
-
-
getCachedURLs
void
傳回目前服務工作者已預先快取的所有網址清單。
getCachedURLs
函式如下所示:() => {...}
-
returns
string[]
預先快取的網址。
-
-
getIntegrityForCacheKey
void
getIntegrityForCacheKey
函式如下所示:(cacheKey: string) => {...}
-
cacheKey
字串
-
returns
字串
與快取鍵相關聯的子資源完整性,如果未設定,則為 undefined。
-
-
getURLsToCacheKeys
void
傳回已快取網址與對應快取索引的對應項目,並考量網址的修訂資訊。
getURLsToCacheKeys
函式如下所示:() => {...}
-
returns
Map<stringstring>
快取金鑰對應的網址。
-
-
安裝
void
預先快取新的素材資源和更新的素材資源。請從服務工作者安裝事件呼叫這個方法。
注意:這個方法會為您呼叫
event.waitUntil()
,因此您不需要在事件處理常式中自行呼叫。install
函式如下所示:(event: ExtendableEvent) => {...}
-
活動
ExtendableEvent
-
returns
Promise<InstallResult>
-
-
matchPrecache
void
這個函式可用來取代
cache.match()
,但有以下差異:- 它知道預先快取的名稱,並只檢查該快取。
- 您可以傳入「原始」網址,而無需提供版本化參數,系統會自動查詢該網址目前有效修訂版本的正確快取鍵。
例如:
matchPrecache('index.html')
會為目前有效的服務工作者找到正確的預先快取回應,即使實際快取鍵為'/index.html?__WB_REVISION__=1234abcd'
也一樣。matchPrecache
函式如下所示:(request: string | Request) => {...}
-
申請。
字串 | 要求
在預先快取中查詢的鍵 (不含修訂參數)。
-
returns
Promise<Response>
-
precache
void
在服務 worker 安裝時,將項目新增至預先快取清單、移除任何重複項目,並將檔案儲存在快取中。
這個方法可以多次呼叫。
precache
函式如下所示:(entries: (string | PrecacheEntry)[]) => {...}
-
項目
(string | PrecacheEntry)[]
-
PrecacheEntry
屬性
-
完整性
string 選填
-
修訂
string 選填
-
網址
字串
PrecacheFallbackPlugin
PrecacheFallbackPlugin
可讓您在特定策略無法產生回應時,指定要使用的「離線備用」回應。
這項作業會攔截 handlerDidError
外掛程式回呼,並傳回已快取的回應,自動考量預期的修訂參數。
除非您明確將 PrecacheController
例項傳入建構函式,否則系統會使用預設例項。一般來說,大多數開發人員都會使用預設值。
屬性
-
建構函式
void
使用相關聯的 fallbackURL 建構新的 PrecacheFallbackPlugin。
constructor
函式如下所示:(config: object) => {...}
-
config
物件
-
fallbackURL
字串
如果相關策略無法產生回應,則會使用預先快取的網址做為備用網址。
-
precacheController
-
-
returns
-
PrecacheRoute
workbox-routing.Route
的子類別,會取得 workbox-precaching.PrecacheController
例項,並使用該例項比對傳入的要求,以及處理從預先快取擷取的回應。
屬性
-
建構函式
void
constructor
函式如下所示:(precacheController: PrecacheController, options?: PrecacheRouteOptions) => {...}
-
precacheController
PrecacheController
例項,用於比對要求並回應擷取事件。 -
選項
-
returns
-
-
catchHandler
-
handler
-
method
HTTPMethod
-
setCatchHandler
void
setCatchHandler
函式如下所示:(handler: RouteHandler) => {...}
-
handler
回呼函式,會傳回解析為回應的承諾
-
PrecacheRouteOptions
屬性
-
cleanURLs
boolean 選填
-
directoryIndex
string 選填
-
ignoreURLParametersMatching
RegExp[] 選填
-
urlManipulation
PrecacheStrategy
workbox-strategies.Strategy
實作項目,專門用於搭配 workbox-precaching.PrecacheController
使用,同時快取及擷取預先快取的素材資源。
注意:建立 PrecacheController
時,系統會自動建立此類別的例項;您通常不需要自行建立。
屬性
-
建構函式
void
constructor
函式如下所示:(options?: PrecacheStrategyOptions) => {...}
-
選項
PrecacheStrategyOptions 選用
-
returns
-
-
cacheName
字串
-
fetchOptions
RequestInit 選填
-
matchOptions
CacheQueryOptions 選填
-
外掛程式
-
copyRedirectedCacheableResponsesPlugin
-
defaultPrecacheCacheabilityPlugin
-
_awaitComplete
void
_awaitComplete
函式如下所示:(responseDone: Promise<Response>, handler: StrategyHandler, request: Request, event: ExtendableEvent) => {...}
-
responseDone
Promise<Response>
-
handler
-
申請。
要求
-
活動
ExtendableEvent
-
returns
Promise<void>
-
-
_getResponse
void
_getResponse
函式如下所示:(handler: StrategyHandler, request: Request, event: ExtendableEvent) => {...}
-
handler
-
申請。
要求
-
活動
ExtendableEvent
-
returns
Promise<Response>
-
-
_handleFetch
void
_handleFetch
函式如下所示:(request: Request, handler: StrategyHandler) => {...}
-
申請。
要求
-
handler
-
returns
Promise<Response>
-
-
_handleInstall
void
_handleInstall
函式如下所示:(request: Request, handler: StrategyHandler) => {...}
-
申請。
要求
-
handler
-
returns
Promise<Response>
-
-
帳號
void
執行要求策略,並傳回
Promise
,該Promise
會與Response
解析,並叫用所有相關外掛程式回呼。當策略例項與 Workbox
workbox-routing.Route
註冊時,系統會在路徑相符時自動呼叫這個方法。或者,您也可以將這個方法傳遞至
event.respondWith()
,以便在獨立的FetchEvent
事件監聽器中使用。handle
函式如下所示:(options: FetchEvent | HandlerCallbackOptions) => {...}
-
選項
FetchEvent | HandlerCallbackOptions
FetchEvent
或含有下列屬性的物件。
-
returns
Promise<Response>
-
-
handleAll
void
與
workbox-strategies.Strategy~handle
類似,但它不會傳回解析為Response
的Promise
,而是會傳回[response, done]
承諾的元組,其中前者 (response
) 等同於handle()
傳回的內容,後者則是承諾,一旦執行策略時新增至event.waitUntil()
的任何承諾完成,就會解析。您可以等待
done
應許,確保策略執行的任何額外工作 (通常是快取回應) 都能順利完成。handleAll
函式如下所示:(options: FetchEvent | HandlerCallbackOptions) => {...}
-
選項
FetchEvent | HandlerCallbackOptions
FetchEvent
或含有下列屬性的物件。
-
returns
[Promise<Response>, Promise<void>]
由 [response, done] 承諾組成的元組,可用於判斷回應何時解析,以及處理程序何時完成所有工作。
-
urlManipulation()
workbox-precaching.urlManipulation(
{ url }: object,
)
類型
函式
參數
-
{ url }
物件
-
網址
網址
-
傳回
-
URL[]
方法
參數
-
外掛程式
addRoute()
workbox-precaching.addRoute(
options?: PrecacheRouteOptions,
)
將 fetch
事件監聽器新增至服務工作者,以便使用預先快取的素材資源回應 [網路要求]https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests
。
針對未預先快取的資產提出要求時,系統不會回應 FetchEvent
,讓事件可傳送至其他 fetch
事件事件監聽器。
參數
-
選項
cleanupOutdatedCaches()
workbox-precaching.cleanupOutdatedCaches()
新增 activate
事件監聽器,這會清理舊版 Workbox 建立的不相容預先快取內容。
createHandlerBoundToURL()
workbox-precaching.createHandlerBoundToURL(
url: string,
)
輔助函式,可在預設 PrecacheController
例項上呼叫 PrecacheController#createHandlerBoundToURL
。
如果您要建立自己的 PrecacheController
,請在該例項上呼叫 PrecacheController#createHandlerBoundToURL
,而不要使用這個函式。
參數
-
網址
字串
預先快取的網址,用於查詢
Response
。
getCacheKeyForURL()
workbox-precaching.getCacheKeyForURL(
url: string,
)
接收網址,並傳回可用於在預先快取中查詢項目的對應網址。
如果提供相對網址,系統會使用服務工作者檔案的位置做為基礎。
如果快取的項目沒有修訂版本資訊,快取鍵就會與原始網址相同。
如果快取的項目含有修訂版本資訊,快取鍵將會是原始網址,並加上用於追蹤修訂版本資訊的查詢參數。
參數
-
網址
字串
要查詢快取鍵的網址。
傳回
-
字串 | 未定義
對應該網址的快取索引鍵。
matchPrecache()
workbox-precaching.matchPrecache(
request: string | Request,
)
輔助函式,可在預設 PrecacheController
例項上呼叫 PrecacheController#matchPrecache
。
如果您要建立自己的 PrecacheController
,請在該例項上呼叫 PrecacheController#matchPrecache
,而不要使用這個函式。
參數
-
申請。
字串 | 要求
在預先快取中查詢的鍵 (不含修訂參數)。
傳回
-
Promise<Response | undefined>
precache()
workbox-precaching.precache(
entries: (string | PrecacheEntry)[],
)
在服務 worker 安裝時,將項目新增至預先快取清單、移除任何重複項目,並將檔案儲存在快取中。
這個方法可以多次呼叫。
請注意:這個方法不會為您提供任何快取檔案。只會預先快取檔案。如要回應網路要求,請呼叫 workbox-precaching.addRoute
。
如果您有要預先快取的單一檔案陣列,只需呼叫 workbox-precaching.precacheAndRoute
即可。
參數
-
項目
(string | PrecacheEntry)[]
precacheAndRoute()
workbox-precaching.precacheAndRoute(
entries: (string | PrecacheEntry)[],
options?: PrecacheRouteOptions,
)
這個方法會將項目新增至預先快取清單,並新增回應擷取事件的路徑。
這是方便方法,可在單一呼叫中呼叫 workbox-precaching.precache
和 workbox-precaching.addRoute
。
參數
-
項目
(string | PrecacheEntry)[]
要預先快取的項目陣列。
-
選項