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);
// optional (default 24 hours)
// The time (in ms) before the service worker cache will automatically expire
app.register(SWcacheDuration, expiry);
}
The browser will automatically register the service worker on page load.
The SWOptionsToken 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
};
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$/],
});
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/],
});
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
fusion-plugin-service-worker's People
fusion-plugin-service-worker's Issues
Browser field not respected in sw bundle when es2015 and es2017 fields also used
Update webpack config so that module imports from src/sw.js
point to the browser and not node.
We want to be populate src/sw.js in apps like this:
import {getHandlers} from "fusion-plugin-service-worker";
export default (assetInfo) => {
const {onFetch, onInstall} = getHandlers(assetInfo);
self.addEventListener("install", onInstall);
self.addEventListener("fetch", onFetch);
}
Currently it has to be long hand like this
// @flow
/* global self, location, fetch, caches, URL */
const cacheName = '0.0.0'; // we don't expect this to change
export default assetInfo => {
const {cacheablePaths, precachePaths} = assetInfo;
self.addEventListener('install', event => {
self.skipWaiting();
event.waitUntil(
// remove old cache
caches
.open(cacheName)
.then(cache => {
return cache
.addAll(precachePaths)
.then(() =>
getOutdatedKeys(cache, cacheablePaths).then(outdatedKeys =>
removeKeys(cache, outdatedKeys)
)
);
})
.catch(e => {
throw new Error('sw: error updating cache' + cacheName + e);
})
);
});
self.addEventListener('fetch', event => {
const HTML_TTL = 1 * 24 * 60 * 60 * 1001; // 1 day
const expectsHtml = requestExpectsHtml(event.request);
if (
!expectsHtml &&
!cacheablePaths.includes(new URL(event.request.url).pathname)
) {
// bypass service worker, use network
return;
}
event.waitUntil(
event.respondWith(
caches.match(event.request).then(cachedResponse => {
if (cachedResponse) {
if (expectsHtml) {
const responseCreated = new Date(
cachedResponse.headers.get('date')
).valueOf();
if (Date.now() - responseCreated > HTML_TTL) {
// html expired: use the cache, but refresh cache for next time
self.fetchNCache(event.request, expectsHtml);
}
}
return cachedResponse;
}
return fetchNCache(event.request, expectsHtml);
})
)
);
});
function getOutdatedKeys(cache) {
return cache.keys().then(requests =>
requests.filter(request => {
return !cacheablePaths.find(key => {
return location.origin + key === request.url;
});
})
);
}
function removeKeys(cache, keys) {
return Promise.all(keys.map(key => cache.delete(key)));
}
function fetchNCache(request, expectsHtml) {
return fetch(request).then(resp => {
if (resp.status !== 200) {
return Promise.resolve(resp);
}
const clonedResponse = resp.clone();
caches.open(cacheName).then(cache => {
if (expectsHtml) {
// check we got html before caching
if (!responseIsHtml(clonedResponse)) {
return Promise.resolve(resp);
}
}
cache.put(request.url, clonedResponse);
});
return Promise.resolve(resp);
});
}
function requestExpectsHtml(request) {
if (!request || !request.headers) {
return false;
}
const acceptHeader = request.headers.get('Accept');
return acceptHeader && acceptHeader.indexOf('html') > -1;
}
function responseIsHtml(response) {
if (!response || !response.headers) {
return false;
}
const contentType = response.headers.get('content-type');
return contentType && contentType.indexOf('html') > -1;
}
};
fix tests
Verify `location.origin` has full support SW browser support
If not, polyfill.
This suggests not supported in safari and opera but in fact it does work correctly in latest desktop version of these browsers. Need to verify latest mobile versions. IE doesn't matter as no SW support.
Edit: forgot Edge which above doc claims might not be supported, but it appears to be: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/5666523/
Use Buildkite and Docker for CI
Handle SW middleware errors
Assign precacehePaths and cacheablePaths to ctx
precachePaths
is an array of core asset paths (usually main.js and vendor.js)cacheablePaths
is a concatenation ofprecachePaths
and all other static assets (could just be JS bundles for phase 1)
A config to specify service-workers only on particular routes
Type of issue
Feature
Description
Servicer workers are the new hotness. However, introducing them to an entire web app can be too spicy. It would be great if to test the SW, we could apply it only on particular routes, instead of an entire app. This feature could be through a configuration when registering the service worker. Maybe, the configuration could accept a whitelist of certain routes that the webapp has.
Make sw.js no-cache
We want browser to default to downloading sw.js each time
Edit: looks life default has changed so SW is no cache by default. Will manually add ctx.set('Cache-Control', 'max-age=0')
in case any non-compliant implementations still out there.
Use template to generate sw.js
Type of issue
Description
Current behavior
Expected behavior
Steps to reproduce
Your environment
-
fusion-plugin-service-worker version:
-
Node.js version (
node --version
): -
npm version (
npm --version
): -
Operating System:
Service worker should unregister itself on js uncaught exception
I think it would be helpful to have the service worker attempt to unregister itself if there's a JS error. Helps stop people from shooting themselves in the foot. I'm open to taking this assuming it's possible / you agree it would be helpful.
Refactor for DI FusionJS
Update README to reflect webpack issue
Type of issue
Description
Current behavior
Expected behavior
Steps to reproduce
Your environment
-
fusion-plugin-service-worker version:
-
Node.js version (
node --version
): -
npm version (
npm --version
): -
Operating System:
Force update SW after some amount of time
Include a daily (or configurable) force-update for users that have long-running sessions? I could see this being an issue for some ubereats.com users
https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#manual_updates
Type of issue
Feature request
Expose logger to service worker
Type of issue
Feature
Description
Expose Logger to SW rather than just logging to console
Dependency deprecation warning: @types/redux (npm)
On registry https://registry.yarnpkg.com/
, the "latest" version (v3.6.0) of dependency @types/redux
has the following deprecation notice:
This is a stub types definition for Redux (https://github.com/reactjs/redux). Redux provides its own type definitions, so you don't need @types/redux installed!
Marking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake.
Affected package file(s): package.json
If you don't care about this, you can close this issue and not be warned about @types/redux
's deprecation again. If you would like to completely disable all future deprecation warnings then add the following to your config:
"suppressNotifications": ["deprecationWarningIssues"]
Generate serviceWorkerTemplateSouce in Webpack
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.