The Fusion plugin for Service Workers.
Out of the box provides default service worker for basic asset caching. Can be fully customized.
yarn add fusion-plugin-service-worker
To use the default service worker, your src/sw.js
should probably look like this:
(you can take advantage of the handlers
module to reduce boilerplate)
import {getHandlers} from 'fusion-plugin-service-worker';
import type {AssetInfo} from 'fusion-plugin-service-worker';
export default (assetInfo) => {
const {onFetch, onInstall, onActivate} = getHandlers(assetInfo);
self.addEventListener("install", onInstall);
self.addEventListener('activate', onActivate);
self.addEventListener("fetch", onFetch);
}
Customize the ServiceWorker by editing src/sw.js
in your app. It shares the same transpile logic as regular fusion bundles.
// src/main.js
import App from 'fusion-react';
import {swTemplate as swTemplateFunction} from 'fusion-cli/sw';
import SwPlugin, {SWTemplateFunctionToken, SWRegisterToken} from 'fusion-plugin-service-worker';
app.register(SwPlugin);
if (__BROWSER__) {
// optional (default true).
// If false will unregister existing service workers and clear cache
app.register(SWRegisterToken, true);
}
if (__NODE__) {
app.register(SWTemplateFunctionToken, swTemplateFunction);
}
The browser will automatically register the service worker on page load.
The SWOptionsToken (NODE only) accepts an object with several optional configuration properties:
type Options = {
cacheableRoutePatterns?: Array<RegExp>, // default null
cacheBustingPatterns?: Array<RegExp>, // default null
cacheDuration?: number, // default 24 hours
};
Array<RegExp>
If this option is supplied the Service Worker will only cache HTML responses from requests whose URL matches at least one of these regular expressions. If the cacheableRoutePatterns
is not supplied, all HTML content will be cached.
app.register(SWOptionsToken, {
cacheableRoutePatterns: [/\/airports$/],
});
Array<RegExp>
If this option is supplied the Service Worker will empty its cache when it encounters a request (for HTML or other resource) which matches at least one of these regular expressions.
app.register(SWOptionsToken, {
cacheBustingPatterns: [/\?logout=true/, /\/display-error/],
});
number
By deafult html caches expire after 24 hours. This expiry period can be overwrriten via this option. See also Cache Expiry.
app.register(SWOptionsToken, {
cacheDuration: 60*60*1000, // one hour
});
Because Service Workers typically cache the HTML there is a possibility that an error or unexpected response will lead to apps being perpetually stuck behind a cache wall and cut off from the network. The Service Worker plugin includes several safeguards that significantly reduce this probability. These include deleting all caches when an HTML request returns a non-200 or non HTML response and backgraound-refreshing the cache from the network after every fetch.
As a last-resort protection, we assign a built-in expiry time to html caches. By default this is 24 hours, but you can override via the SWOptionsToken
token (see cacheDuration option above). This is recommended when shipping a Service Worker for the first time, so as to prevent network isolation until the app owner is confident the Service Worker Plugin is working as expected.
The Service Worker sends status updates to the browser client in the form of postMessages. These messages take the form:
{
type: string,
text: string
}
Your app can listen to these post messages and filter by type:
if ('serviceWorker' in window.navigator) {
window.navigator.serviceWorker.addEventListener('message', event => {
if (existingSW && event.data.type === 'upgrade-available') {
// prompt user to reload for new build
logger.log(event.data.text);
}
});
}
Message types include:
upgrade-available: A new build has occured and the user should reload the page to get the latest version. The service worker plugin will console.log
this message by default
cache-expired: The Service Worker cache wan not been updated for a period exceeding the cache expiry period (see above) and so has been auto-refreshed.
If you need all users to unregister the Service Worker, you can register SWRegisterToken
with the value false
if (__BROWSER__) {
app.register(SWRegisterToken, false);
}
For more information on how to use the Fusion Service Worker Plugin and an explanation of Service Workers in general, please see the Service Workers section in the Fusion.js Guide