網頁應用程式中的某些資產可能不常使用、非常大,或是會因使用者裝置 (例如回應式圖片) 或語言而有所不同。這些是預先快取可能為反模式的執行個體,您應改用執行階段快取功能。
在 Workbox 中,您可以使用 workbox-routing
模組處理資產的執行階段快取以比對路徑,並使用 workbox-strategies
模組處理資產的快取策略。
快取策略
您可使用其中一種內建的快取策略,處理大部分的資產路徑。這份說明文件先前有詳細說明,以下提供幾點重點回顧:
- 「過時的舊作」會根據要求使用快取回應 (如果要求可用),並使用網路的回應更新背景快取。因此,如果資產未快取,就會等待網路回應並使用該資產。由於 SCC 會定期更新仰賴它的快取項目,因此這是非常安全的策略。缺點是一律在背景中向網路要求素材資源。
- 網路優先會嘗試先從網路取得回應。如果收到回應,就會將回應傳遞至瀏覽器,並將其儲存至快取。如果網路要求失敗,系統會使用最後一個快取的回應,啟用該資產的離線存取功能。
- 先快取會檢查回應的快取,接著再採用回應 (如果可用)。如果要求不在快取中,系統會使用網路,並將任何有效回應新增至快取,然後再傳送至瀏覽器。
- 「僅限網路」會強制來自網路。
- 「僅限快取」會強制要求來自快取的回應。
您可以使用 workbox-routing
提供的方法,套用這些策略來選取要求。
套用路徑比對的快取策略
workbox-routing
會公開 registerRoute
方法,以便比對路徑並透過快取策略處理這些路徑。registerRoute
接受 Route
物件,而這個物件又會接受兩個引數:
建議比對回呼,因為它們提供的結構定義物件包含 Request
物件、要求網址字串、擷取事件,以及指出要求是否為相同來源要求的布林值。
處理常式會處理相符的路線。在以下範例中,系統會建立與傳入的相同來源圖片要求相符的新路徑,並先套用快取,再改回網路策略。
// sw.js
import { registerRoute, Route } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
// A new route that matches same-origin image requests and handles
// them with the cache-first, falling back to network strategy:
const imageRoute = new Route(({ request, sameOrigin }) => {
return sameOrigin && request.destination === 'image'
}, new CacheFirst());
// Register the new route
registerRoute(imageRoute);
使用多個快取
Workbox 可讓您使用套裝組合策略中的 cacheName
選項,將快取回應值區分至不同的 Cache
執行個體。
在以下範例中,圖片使用過時後的重新驗證策略,而 CSS 和 JavaScript 素材資源則使用快取優先改回網路策略。每個資產的路徑會新增 cacheName
屬性,將回應放入不同的快取。
// sw.js
import { registerRoute, Route } from 'workbox-routing';
import { CacheFirst, StaleWhileRevalidate } from 'workbox-strategies';
// Handle images:
const imageRoute = new Route(({ request }) => {
return request.destination === 'image'
}, new StaleWhileRevalidate({
cacheName: 'images'
}));
// Handle scripts:
const scriptsRoute = new Route(({ request }) => {
return request.destination === 'script';
}, new CacheFirst({
cacheName: 'scripts'
}));
// Handle styles:
const stylesRoute = new Route(({ request }) => {
return request.destination === 'style';
}, new CacheFirst({
cacheName: 'styles'
}));
// Register routes
registerRoute(imageRoute);
registerRoute(scriptsRoute);
registerRoute(stylesRoute);
為快取項目設定到期日
管理 Service Worker 快取時須留意儲存空間配額。ExpirationPlugin
可簡化快取維護工作,並由 workbox-expiration
公開。如要使用,請在快取策略的設定中指定:
// sw.js
import { registerRoute, Route } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
import { ExpirationPlugin } from 'workbox-expiration';
// Evict image cache entries older thirty days:
const imageRoute = new Route(({ request }) => {
return request.destination === 'image';
}, new CacheFirst({
cacheName: 'images',
plugins: [
new ExpirationPlugin({
maxAgeSeconds: 60 * 60 * 24 * 30,
})
]
}));
// Evict the least-used script cache entries when
// the cache has more than 50 entries:
const scriptsRoute = new Route(({ request }) => {
return request.destination === 'script';
}, new CacheFirst({
cacheName: 'scripts',
plugins: [
new ExpirationPlugin({
maxEntries: 50,
})
]
}));
// Register routes
registerRoute(imageRoute);
registerRoute(scriptsRoute);
遵守儲存空間配額可能相當複雜。建議您考慮使用者可能遇到儲存壓力,或想要最有效運用儲存空間的使用者。Workbox 的ExpirationPlugin
對夥伴可協助您達成這項目標。
跨來源注意事項
Service Worker 和跨來源資產之間的互動,遠與相同來源資產有極大差異。跨源資源共享 (CORS) 較為複雜,而複雜程度會擴及服務工作站中跨來源資源的處理方式。
不透明回應
在 no-cors
模式中提出跨來源要求時,回應可以儲存在 Service Worker 快取中,甚至供瀏覽器直接使用。不過,無法透過 JavaScript 讀取回應主體。這就是所謂的不透明回應。
不透明回應是一種安全措施,用於防止檢查跨來源資產。您仍可提出跨來源資產要求,甚至快取這些資產,只是無法讀取回應內文,甚至無法讀取回應狀態碼!
記得選擇啟用 CORS 模式
即使您載入的跨來源素材資源「確實」設定了許可 CORS 標頭讓您讀取回應,跨來源回應的內文可能仍不透明。舉例來說,下列 HTML 會觸發 no-cors
要求,無論設定哪些 CORS 標頭為何,都可能產生不透明的回應:
<link rel="stylesheet" href="https://example.com/path/to/style.css">
<img src="https://example.com/path/to/image.png">
如要明確觸發會產生非不透明回應的 cors
要求,您必須在 HTML 中加入 crossorigin
屬性,明確選擇使用 CORS 模式:
<link crossorigin="anonymous" rel="stylesheet" href="https://example.com/path/to/style.css">
<img crossorigin="anonymous" src="https://example.com/path/to/image.png">
當 Service Worker 中的路徑在執行階段中載入子資源時,請務必記住這個重點。
Workbox 可能無法快取不透明回應
根據預設,Workbox 會謹慎快取不透明回應。您無法檢查回應代碼是否有不透明的回應,因此如果使用優先快取或僅限快取的策略,快取錯誤回應可能會導致持續中斷的體驗。
如果需要在 Workbox 中快取不透明回應,您應使用「網路優先」或「過時即驗證」的策略來處理。是的,這表示網路每次仍會請求該素材資源,但這樣可確保失敗的回應不會保留,而且最終會替換為可用的回應。
如果您使用其他快取策略,且傳回不透明回應,Workbox 會警告,在開發模式下,並未快取回應。
強制快取不透明回應
如果您「絕對」想使用優先快取或僅限快取策略快取不透明回應,可以使用 workbox-cacheable-response
模組強制 Workbox 執行此操作:
import {Route, registerRoute} from 'workbox-routing';
import {NetworkFirst, StaleWhileRevalidate} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';
const cdnRoute = new Route(({url}) => {
return url === 'https://cdn.google.com/example-script.min.js';
}, new CacheFirst({
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200]
})
]
}))
registerRoute(cdnRoute);
不透明回應和 navigator.storage
API
為避免跨網域資訊外洩,系統在計算儲存空間配額限制時,系統會為不透明回應大小加上明顯的邊框間距。這會影響 navigator.storage
API 回報儲存空間配額的方式。
這個邊框間距會因瀏覽器而異,但在 Chrome 中,任何單一快取不透明回應的大小下限為約 7 MB 的儲存空間。當您決定要快取的不透明回應數量時,請留意這一點,因為這樣您就可以比預期更快地超出儲存空間配額。