import { clientsClaim, skipWaiting } from 'workbox-core'; import { cleanupOutdatedCaches, precacheAndRoute, matchPrecache, } from 'workbox-precaching'; import { registerRoute, setDefaultHandler, setCatchHandler, } from 'workbox-routing'; import { CacheableResponsePlugin } from 'workbox-cacheable-response'; import { CacheFirst, StaleWhileRevalidate, NetworkFirst, NetworkOnly, } from 'workbox-strategies'; import { ExpirationPlugin } from 'workbox-expiration'; import { BroadcastUpdatePlugin } from 'workbox-broadcast-update'; import * as googleAnalytics from 'workbox-google-analytics'; const OFFLINE_FALLBACK = '/offline-fallback.html'; precacheAndRoute(self.__WB_MANIFEST, { // Ignore all URL parameters: // https://developers.google.com/web/tools/workbox/modules/workbox-precaching#ignore_url_parameters ignoreURLParametersMatching: [/.*/], }); cleanupOutdatedCaches(); // default strategy setDefaultHandler( new StaleWhileRevalidate({ cacheName: 'default', plugins: [new BroadcastUpdatePlugin()], }) ); // Never cache ranged requests (videos) registerRoute(({ request }) => request.headers.has('range'), new NetworkOnly()); // Google Analytics registerRoute( ({ request }) => request.url === 'https://www.google-analytics.com/analytics.js', new CacheFirst({ cacheName: 'shell', plugins: [ new ExpirationPlugin({ maxAgeSeconds: 10 * 24 * 60 * 60, // 10 Days }), ], }) ); // Pages // Try to get fresh HTML from network, but don't wait for more than 2 seconds registerRoute( ({ request }) => request.destination === 'document', new NetworkFirst({ cacheName: 'pages', networkTimeoutSeconds: 2, plugins: [new BroadcastUpdatePlugin()], }) ); // Images registerRoute( ({ request }) => request.destination === 'image', new StaleWhileRevalidate({ cacheName: 'images', plugins: [ new CacheableResponsePlugin({ statuses: [0, 200], }), new ExpirationPlugin({ maxEntries: 200, maxAgeSeconds: 90 * 24 * 60 * 60, // 90 Days }), ], }) ); setCatchHandler(({ event }) => { switch (event.request.destination) { case 'document': return matchPrecache(OFFLINE_FALLBACK); case 'image': return new Response( '<svg role="img" aria-labelledby="offline-title" viewBox="0 0 400 225" xmlns="https://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice"><title id="offline-title">Offline</title><path fill="rgba(145,145,145,0.5)" d="M0 0h400v225H0z" /><text fill="rgba(0,0,0,0.33)" font-family="Georgia,serif" font-size="27" text-anchor="middle" x="200" y="113" dominant-baseline="central">offline</text></svg>', { headers: { 'Content-Type': 'image/svg+xml' } } ); default: return Response.error(); } }); googleAnalytics.initialize({ hitFilter: (params) => { const queueTimeInSeconds = Math.round(params.get('qt') / 1000); params.set('cm1', queueTimeInSeconds); }, parameterOverrides: { cd4: 'offline', }, }); skipWaiting(); clientsClaim();