- Why Should I Use a Service Worker?
- Terminology
- Add
sw-precache
to Your Build - Examples
- Other Resources
You have a web app, and you'd like it to load quickly and work offline.
You'd like to use proven tools to handle the details for you, to work around common gotchas and follow best practices.
A service worker is a background script that intercepts network requests made by your web app. It can use the Cache Storage API to respond to those requests.
You do not have to write your own service worker script; this guide will explain how to generate one customized for your web app.
"App Shell" refers to the local resources that your web app needs to load its basic structure. This will always include some HTML, and will likely also include CSS and JavaScript, either inline or in external files.
Some static web apps consist entirely of an App Shell.
A helpful analogy is to think of your App Shell as the code and resources that would be published to an app store for a native iOS or Android application.
The App Shell should ideally be loaded directly from the local cache, just like a native iOS or Android application is loaded directly from a device's storage.
The dynamic content is all of the data, images, and other resources that your web app needs to function, but exists independently from your App Shell.
Sometimes this data will come from external, third-party APIs, and sometimes this will be first-party data that is dynamically generated or frequently updated.
For example, if your web app is for a newspaper, it might make use of a first-party API to fetch recent articles, and a third-party API to fetch the current weather. Both of those types of requests fall into the category of "dynamic content".
Unlike the App Shell, dynamic content is usually ephemeral, and it's important to choose the right caching strategy for each source of dynamic content.
You should always use a
cache-first strategy
for your App Shell. sw-precache
handles the details of that for you.
However, the right caching strategy for your dynamic content is not always clear-cut. It's recommended that you read through the The Offline Cookbook and think about which strategy provides the right balance between speed and data freshness for each of your data sources.
Regardless of which strategy you choose, sw-precache
handles the
implementation for you. All of the standard caching strategies, along with
control over advanced options like maximum cache size and age, are supported via
the automatic inclusion of the sw-toolbox
library.
sw-precache
should be automated to run as part of your site's existing build
process. It's important that it's re-run each time any of your App Shell
resources change, so that it can pick up the latest versions.
It is available as a Node module for use in Gulp,
Grunt, or other Node-based build systems. It is also
available as a command-line binary, suitable for inclusion as part of an
npm
-based build.
A basic configuration for a web app that relies entirely on local resources, all
located as subdirectories of an app
directory, might look like:
{
staticFileGlobs: ['app/**/*.{js,html,css,png,jpg,gif}'],
stripPrefix: 'app',
// ...other options as needed...
}
Once you've chosen an appropriate caching strategy to use for your dynamic
content, you can tell sw-precache
which
strategies to
use for runtime requests that match specific URL patterns:
{
runtimeCaching: [{
urlPattern: new RegExp('^https://example\.com/api'),
handler: 'networkFirst'
}, {
urlPattern: new RegExp('/articles/'),
handler: 'fastest',
options: {
cache: {
maxEntries: 10,
name: 'articles-cache'
}
}
}],
// ...other options as needed...
}
If you use the runtimeCaching
option, sw-precache
will automatically include
the sw-toolbox
library and the
corresponding routing configuration
in the service worker file that it generates.
If your web app relies on server-side templating to use several partial files to
construct your App Shell's HTML, it's important to let sw-precache
know about
those dependencies.
For example, if your web app has two pages, /home
and /about
, each of which
depends on a both a shared master template and a page-specific template, you can
represent those dependencies as follows:
{
dynamicUrlToDependencies: {
'/home': ['templates/master.hbs', 'templates/home.hbs'],
'/about': ['templates/master.hbs', 'templates/about.hbs']
},
// ...other options as needed...
}
A common pattern when developing
single page applications
(SPAs) is to bootstrap initial navigations with an App Shell, and then load
dynamic content based on URL routing rules. sw-precache
supports this with the
concept of a "fallback URL":
{
navigateFallback: '/app-shell',
// ...other options as needed...
}
In this configuration, whenever the service worker intercepts a
navigate request for a
URL that doesn't exist in the cache, it will respond with the cached contents of
/app-shell
. It's up to you to ensure that /app-shell
contains all of the
resources needed to bootstrap your SPA.
There are several ready-made examples of varying complexity that use
sw-preache
as part of their build process:
- https://github.com/GoogleChrome/sw-precache/tree/master/demo
- https://github.com/GoogleChrome/sw-precache/tree/master/app-shell-demo
- https://github.com/GoogleChrome/application-shell
- https://github.com/GoogleChrome/ioweb2015