-
Notifications
You must be signed in to change notification settings - Fork 9
Caching with Service Worker
Below are dev notes for creating a custom Service Worker template for caching Seafoodfest web app assets.
1. Register the Service Worker
src/index.js calls serviceWorker.register();
By default, this is commented out when scaffolding a React app with create-react-app CLI.
2. Update registerServiceWorker.js
In src/registerServiceWorker.js, update the register function such that the load event will generate a sw.js file instead of the default service-worker.js file after doing a build.
In this solution we made the following changes:
//const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
const swUrl = `${process.env.PUBLIC_URL}/sw.js`;
3. Create service worker build file
Added src/sw-build.js with the following:
const workboxBuild = require('workbox-build');
// NOTE: This should be run *AFTER* all your assets are built
const buildSW = () => {
// This will return a Promise
return workboxBuild.injectManifest({
swSrc: 'src/sw-template.js', // this is your sw template file
swDest: 'build/sw.js', // this will be created in the build step
globDirectory: 'build',
globPatterns: [
'**\/*.{js,css,html,png}',
]
}).then(({count, size, warnings}) => {
// Optionally, log any warnings and details.
warnings.forEach(console.warn);
console.log(`${count} files will be precached, totaling ${size} bytes.`);
});
}
buildSW();
4. Create service worker template file
Added src/sw-template.js with the below. Note, the Workbox cache rules need to be tweaked as needed for SeafoodFest.
if ('function' === typeof importScripts) {
importScripts(
'https://storage.googleapis.com/workbox-cdn/releases/3.5.0/workbox-sw.js'
);
/* global workbox */
if (workbox) {
console.log('Workbox for SFF is loaded');
/* injection point for manifest files. */
workbox.precaching.precacheAndRoute([]);
/* custom cache rules */
workbox.routing.registerNavigationRoute('/index.html', {
blacklist: [/^\/_/, /\/[^\/]+\.[^\/]+$/],
});
/*
Custom cache rules - app images
Cache all image types.
Get images from the cache first.
Fetch new images every 30 days so they are not stale - image update are NOT frequent.
*/
workbox.routing.registerRoute(
/\.(?:png|gif|jpg|jpeg|svg)$/,
workbox.strategies.cacheFirst({
cacheName: 'sf-images',
plugins: [
new workbox.expiration.Plugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
})
],
})
);
/*
Custom cache rules - json
Cache .geojson files.
Fetch garagesale.geojson from the network first if possible (as they are updated frequently).
Fallback to the cached garagesale.geojson if disconnected from the internet.
*/
workbox.routing.registerRoute(
new RegExp('.*\.json'),
new workbox.strategies.NetworkFirst({
cacheName: 'sf-json'
})
);
/*
Custom cache rules - map tiles
Cache map tiles from the external mapbox root url - for only successfull responses.
*/
workbox.routing.registerRoute(
new RegExp('^https://api.mapbox.com/v4/mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v7,spatialdev.45mt0wo1,spatialdev.00lrg24b/'),
new workbox.strategies.CacheFirst({
cacheName: 'sf-map-tile-cache',
plugins: [
new workbox.cacheableResponse.Plugin({
statuses: [0, 200],
})
]
})
);
// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
workbox.routing.registerRoute(
/^https:\/\/fonts\.googleapis\.com/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'google-fonts-stylesheets'
})
);
// Cache the underlying font files with a cache-first strategy for 1 year.
workbox.routing.registerRoute(
/^https:\/\/fonts\.gstatic\.com/,
new workbox.strategies.CacheFirst({
cacheName: 'google-fonts-webfonts',
plugins: [
new workbox.cacheableResponse.Plugin({
statuses: [0, 200]
}),
new workbox.expiration.Plugin({
maxAgeSeconds: 60 * 60 * 24 * 365,
maxEntries: 30
}),
],
})
);
} else {
console.log('Workbox could not be loaded. No Offline support');
}
}
5. Update package.json to add build step and clean-up for Service Worker
"scripts": {
"start": "react-scripts start",
"build-sw": "node ./src/sw-build.js", // <!--- ADDED THIS - BUILD THE CUSTOM SERVICE WORKER
"clean-cra-sw": "rm -f build/precache-manifest.*.js && rm -f build/service-worker.js", <!-- ADDED THIS - CLEAN UP
"build": "react-scripts build && npm run build-sw && npm run clean-cra-sw", <!--- UPDATED THIS - ADD BUILD STEP
"test": "react-scripts test",
"eject": "react-scripts eject"
},