One feature of service workers is the ability to save files to the cache when the service worker is installing. This is referred to as "precaching". Precaching makes it possible to serve cached files to the browser without going to the network. Use precaching for critical assets that your site needs even when offline: main page, styles, fallback image and essential scripts.
Why should you use Workbox?
Using Workbox for precaching is optional. You can write your own code to precache critical assets when the service worker is installing. The primary benefit of using Workbox is its out-of-the-box version control. You'll run into a lot less trouble updating precached assets using Workbox than if you had to manage the versioning and updating of these files on your own.
Precache manifests
Precaching is driven by a list of URLs and associated versioning information for each URL. Taken together, this information is known as a precache manifest. The manifest is the "source of truth" for the state of everything meant to be in the precache for a given version of a web app. A precache manifest, in the format used by Workbox, looks something like:
[{
url: 'app.abcd1234.js'
}, {
url: 'offline.svg',
revision: '7836745f'
}, {
url: 'index.html',
revision: '518747aa'
}]
When the service worker is installed, three cache entries are created in the
Cache Storage, for each of the three listed URLs. The first asset has versioning
information already included in its URL (app
is the actual file name, and
.abcd1234
contains the versioning information, right before the file extension
.js
). Workbox's build tools can detect this and exclude a revision field. The
other two assets do not include any versioning info in their URLs, so Workbox's
build tools create a separate revision
field, containing a hash of the local
file's contents.
Serving precached resources
Adding assets to the cache is just one part of the precaching story—once the
assets are cached, they need to respond to outgoing requests. That requires a
fetch
event listener in your service worker that can check which URLs have
been precached, and return those cached responses reliably, bypassing the
network in the process. Since the service worker checks the cache for responses
(and uses those before the network), this is called a
cache-first strategy.
Efficient updates
A precache manifest provides an exact representation of the expected cache state; if a URL/revision combination in the manifest changes, a service worker knows that the previous cached entry is no longer valid, and needs to be updated. It only takes a single network request, made automatically by the browser as part of the service worker update check, to determine which precached URLs need to be refreshed.
Updates to precached resources
As you release new versions of your web app over time, you need to keep previously precached URLs up to date, precache new assets, and delete outdated entries. As long as you continue generating a full precache manifest each time you rebuild your site, that manifest serves as the "source of truth" for your precache state at any point in time.
If there's an existing URL with a new revision field, or if any URLs have been
added or dropped from the manifest, that's a sign to your service worker that
updates need to be performed, as part of the
install
and
activate
event handlers. For instance, if you've made some changes to your site and
rebuilt, your latest precache manifest might have undergone the following
changes:
[{
url: 'app.ffaa4455.js'
}, {
url: 'offline.svg',
revision: '7836745f'
}, {
url: 'index.html',
revision: '518747aa'
}]
Each of these changes tells your service worker that new requests need to be
made to update previously cached entries ('offline.svg'
and 'index.html'
)
and cache new URLs ('app.ffaa4455.js'
), as well as deletions to clean up URLs
that are no longer used ('app.abcd1234.js'
).
True "app store" install experience
Another benefit of precaching is that you can give your users an experience that would otherwise be difficult to achieve outside of an "app store" installation. Once a user visits any page on your web app for the first time, you can potentially precache all of the URLs needed to display any of your web app's views ahead of time, without having to wait until they visit each individual view.
When a user installs an app, they expect every part to display quickly, not just the views that they've gone to in the past. Precaching brings that same experience to web apps.
Which of your assets should be precached?
Refer back to the Identify what's being loaded guide to get a good picture of which URLs make the most sense to precache. The general rule is to precache any HTML, JavaScript, or CSS that's loaded early on and is crucial to displaying the basic structure of a given page.
It's preferable to avoid precaching media or other assets that are loaded later (unless crucial for your web app's functionality). Instead, use a runtime caching strategy to ensure these assets are cached-as-you-go.
Always keep in mind that precaching involves using network bandwidth and storage on a user's device (just like installing an app from an app store does). It's up to you as the developer to precache judiciously, and avoid a bloated precache manifest.
Workbox's build tools help by telling you the number of items in the precache manifest as well as the total size of the precache payload.
Repeat visitors to your web app benefit in the long run from the upfront cost of precaching, since the ability it offers to avoid the network quickly pays for itself in saved bandwidth over time.