import { ExpirationPlugin } from 'workbox-expiration' import { cleanupOutdatedCaches, precacheAndRoute } from 'workbox-precaching' import { offlineFallback } from 'workbox-recipes' import { Route, registerRoute, setDefaultHandler } from 'workbox-routing' import { NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies' declare let self: ServiceWorkerGlobalScope const HOUR = 60 * 60 const DAY = 24 * HOUR const YEAR = 365 * DAY const MONTH = YEAR / 12 self.addEventListener('message', (event) => { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (event.data && event.data.type === 'SKIP_WAITING') { void self.skipWaiting() } }) cleanupOutdatedCaches() // Filter EN files on the FR app and vice versa const precache = self.__WB_MANIFEST.filter( (entry) => typeof entry !== 'string' && !entry.url.includes( location.href.startsWith(import.meta.env.VITE_FR_BASE_URL) ? 'infrance' : 'mon-entreprise' ) ) precacheAndRoute(precache) // Allow work offline offlineFallback({ // When the user is offline and loads a page that is not cached, we return the French/English index file. pageFallback: location.href.startsWith(import.meta.env.VITE_FR_BASE_URL) ? '/mon-entreprise.html' : '/infrance.html', }) // Set the default handler with network first so that every requests (css, js, html, image, etc.) // goes through the service worker and will be cache setDefaultHandler( new NetworkFirst({ cacheName: 'default-network-first', plugins: [ new ExpirationPlugin({ maxAgeSeconds: 3 * MONTH, maxEntries: 40, }), ], }) ) const networkFirstJS = new Route( ({ sameOrigin, url }) => { return sameOrigin && /assets\/.*\.js$/.test(url.pathname) }, new NetworkFirst({ cacheName: 'js-cache', plugins: [ new ExpirationPlugin({ maxAgeSeconds: 1 * MONTH, maxEntries: 40, }), ], }) ) registerRoute(networkFirstJS) const staleWhileRevalidate = new Route( ({ request, sameOrigin, url }) => { return ( sameOrigin && (url.pathname.startsWith('/twemoji/') || request.destination === 'image' || request.destination === 'font') ) }, new StaleWhileRevalidate({ cacheName: 'media', plugins: [ new ExpirationPlugin({ maxAgeSeconds: 1 * YEAR, maxEntries: 150, purgeOnQuotaError: true, }), ], }) ) registerRoute(staleWhileRevalidate) const networkFirstPolyfill = new Route( ({ sameOrigin, url }) => { return !sameOrigin && url.hostname === 'polyfill.io' }, new NetworkFirst({ cacheName: 'external-polyfill', plugins: [ new ExpirationPlugin({ maxAgeSeconds: 3 * MONTH, maxEntries: 5, }), ], }) ) registerRoute(networkFirstPolyfill) const networkFirstAPI = new Route( ({ sameOrigin, url }) => { return ( (!sameOrigin && [ 'api.recherche-entreprises.fabrique.social.gouv.fr', 'geo.api.gouv.fr', ].includes(url.hostname)) || (sameOrigin && /data\/.*\.json$/.test(url.pathname)) ) }, new NetworkFirst({ cacheName: 'external-api', plugins: [ new ExpirationPlugin({ maxAgeSeconds: 7 * DAY, maxEntries: 40, }), ], }) ) registerRoute(networkFirstAPI)