Skip to content

Instantly share code, notes, and snippets.

@marcveens
Created March 22, 2021 22:27
Show Gist options
  • Select an option

  • Save marcveens/57b32abdff7d3b8d77ef4bbf8c3b934c to your computer and use it in GitHub Desktop.

Select an option

Save marcveens/57b32abdff7d3b8d77ef4bbf8c3b934c to your computer and use it in GitHub Desktop.
service-worker.ts used for a SSR React website
// Source: https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox-recipes_googleFontsCache.js?hl=en
/*
Copyright 2020 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
import { registerRoute } from 'workbox-routing/registerRoute.js';
import { StaleWhileRevalidate } from 'workbox-strategies/StaleWhileRevalidate.js';
import { CacheFirst } from 'workbox-strategies/CacheFirst.js';
import { CacheableResponsePlugin } from 'workbox-cacheable-response/CacheableResponsePlugin.js';
import { ExpirationPlugin } from 'workbox-expiration/ExpirationPlugin.js';
/**
* An implementation of the [Google fonts]{@link /web/tools/workbox/guides/common-recipes#google_fonts} caching recipe
*
* @memberof module:workbox-recipes
*
* @param {Object} [options]
* @param {string} [options.cachePrefix] Cache prefix for caching stylesheets and webfonts. Defaults to google-fonts
* @param {number} [options.maxAgeSeconds] Maximum age, in seconds, that font entries will be cached for. Defaults to 1 year
* @param {number} [options.maxEntries] Maximum number of fonts that will be cached. Defaults to 30
*/
function googleFontsCache(options: any = {}) {
const sheetCacheName = `${options.cachePrefix || 'google-fonts'}-stylesheets`;
const fontCacheName = `${options.cachePrefix || 'google-fonts'}-webfonts`;
const maxAgeSeconds = options.maxAgeSeconds || 60 * 60 * 24 * 365;
const maxEntries = options.maxEntries || 30;
// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
registerRoute(({ url }) => url.origin === 'https://fonts.googleapis.com', new StaleWhileRevalidate({
cacheName: sheetCacheName,
}));
// Cache the underlying font files with a cache-first strategy for 1 year.
registerRoute(({ url }) => url.origin === 'https://fonts.gstatic.com', new CacheFirst({
cacheName: fontCacheName,
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
new ExpirationPlugin({
maxAgeSeconds,
maxEntries,
}),
],
}));
}
export { googleFontsCache };
/// <reference lib="webworker" />
/* eslint-disable no-restricted-globals */
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { clientsClaim } from 'workbox-core';
import { ExpirationPlugin } from 'workbox-expiration';
import { NavigationRoute, registerRoute } from 'workbox-routing';
import { NetworkOnly, StaleWhileRevalidate } from 'workbox-strategies';
import { precacheAndRoute } from 'workbox-precaching';
import { googleFontsCache } from './ServiceWorker/googleFontsCache';
import { PrecacheEntry } from 'workbox-precaching/_types';
declare const self: ServiceWorkerGlobalScope;
clientsClaim();
const manifest = self.__WB_MANIFEST;
const thirtyDaysInSeconds = 60 * 60 * 24 * 30;
const cacheNames = {
appImages: 'app-image',
appFetch: 'app-fetch'
};
const indexHtmlManifestItem = manifest.find((item) => typeof item !== 'string' && item.url.includes('index.html')) as PrecacheEntry;
const indexHtmlKey = indexHtmlManifestItem ? `${indexHtmlManifestItem.url}?__WB_REVISION__=${indexHtmlManifestItem.revision}` : '';
precacheAndRoute(manifest);
self.addEventListener('install', function () {
console.log('Installed service worker');
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
cleanOldCaches(event);
});
// Make sure all other routes like /zoeken are handled by index.html in offline mode
const navigationHandler = async (params) => {
try {
// Attempt a network request.
return await new NetworkOnly().handle(params);
} catch (error) {
// If it fails, return the cached HTML.
return caches.match(indexHtmlKey);
}
};
const navigationRoute = new NavigationRoute(navigationHandler);
registerRoute(navigationRoute);
// Cache Google fonts
googleFontsCache();
// Register all app/images which are statically served
registerRoute(
({ url, sameOrigin }) => {
const match = url.pathname.match(/app\/images\/(.*)\.(jpe?g|png|woff2?|svg)$/);
return sameOrigin && match && match.length > 0;
},
new StaleWhileRevalidate({
cacheName: cacheNames.appImages,
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
new ExpirationPlugin({
maxAgeSeconds: thirtyDaysInSeconds
}),
]
})
);
// Store certain fetch results for offline use
registerRoute(
({ url, sameOrigin }) => {
const isPageLayout = url.search.includes('/sitesettings/pagelayout');
return sameOrigin && isPageLayout;
},
new StaleWhileRevalidate({
cacheName: cacheNames.appFetch,
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
})
]
})
);
// Remove all outdated cache lists. Note that this does not check every record
const cleanOldCaches = (event: ExtendableEvent) => {
event.waitUntil(caches.keys().then(async keyList => {
for (const key of keyList) {
if (!Object.values(cacheNames).includes(key) && !key.startsWith('workbox-precache') && !key.startsWith('google-fonts')) {
console.log('delete cache ', key);
await caches.delete(key);
}
}
}));
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment