網頁應用程式中的某些資產可能不常使用、非常大,或是會因使用者的裝置 (例如回應式圖片) 或語言而有所不同。這類執行個體預先快取可能具有反模式,而您應該改用執行階段快取。
在 Workbox 中,您可以使用 workbox-routing
模組來比對路徑,處理資產的執行階段快取,並使用 workbox-strategies
模組處理資產的快取策略。
快取策略
您可以利用其中一種內建的快取策略來處理大部分的資產路徑。雖然我們提早在說明文件中詳細說明這些做法,但還是值得回顧:
- WvalidateI 會將快取回應用於要求 (如果有的話),並透過網路回應更新背景的快取。因此,如果系統未快取資產,則會等待網路回應並使用該資產。因為這項策略會定期更新依賴該策略的快取項目,因此是相當安全的策略。但缺點是一律在背景向網路要求素材資源。
- Network First 會先嘗試從網路取得回應。如果系統收到回應,就會將該回應傳送至瀏覽器,並將其儲存至快取。如果網路要求失敗,系統會使用最後一個快取的回應,啟用資產的離線存取功能。
- 「先快取」會先檢查快取,並在可用的情況下使用回應。如果要求不在快取中,則會使用網路,並在傳送至瀏覽器之前,將所有有效的回應加入快取。
- Network Only 可強制要求回應來自網路。
- 僅快取可強制要求來自快取。
您可以使用 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) 很複雜,這種複雜性牽涉到在 Service Worker 中處理跨源資源的方式。
不透明回應
以 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。決定您要快取的不透明回應數量時,請務必記住這一點,因為您可能會比預期更快超過儲存空間配額。