A service worker is a script that your browser runs in the background, separate from a web page, opening the door to features that don't need a web page or user interaction. They already include features like push notifications and background sync.
– Google web developer documentation
ScandiPWA makes use of the service worker to cache requests on the client-side.
<aside> ➡️ The service worker cache does not expire by default. Expiration needs to be configured manually – and images, for example, are configured to cache the 50 latest entries, forgetting the rest.
</aside>
The current caching behavior is implemented in src/service-worker.js
. It registers several cache routes, each with its own caching behavior:
<aside> ➡️ Document (HTML page) requests are only served from cache if a user is offline.
</aside>
registerRoute
work?The registerRoute
takes two arguments:
ExtendableEvent
, Request
, and a URL
object you can match by returning a truthy value. If you return false, the rule is ignored for the request.<aside> ➡️ Note: Often, instead of manually defining functions, you will use helpers. For example, the first argument can also be a regular expression, and the second argument can be one of the strategies provided by workbox strategies. What are workbox strategies?
</aside>
Where can I find the official registerRoute
documentation?
To add a new cache rule:
src/service-worker.js
file by copying it into your themeregisterRoute
call<aside> ➡️ Check the existing rules as examples!
</aside>
To avoid caching a file that is currently cached:
src/service-worker.js
file by copying it into your themeregisterRoute
call is matching the fileFor some projects, you might want to change the behavior of the "a new version is available" popups.
The main problem with caching resources is that the cached version may become outdated when the resource is updated.
If the service worker detects that it has cached an old version of the page, it will prompt the user to refresh the page. This is necessary because the updated version can only be fetched when the page is refreshed.
In some cases, you may wish to change the default behavior of the version updates.
<aside>
➡️ How is the "new version" detection implemented? When a new build is available, there is also a new service worker. The new service worker replaces the old one – and the controllerchange
event tells us that there has been a service worker update. When there is a new service worker, we know that there's also possibly other new content!
</aside>
By default, the user has a choice if they want to update immediately or not. If they choose to not refresh the page, they will continue using the old version
Pros:
Cons:
This is implemented in the NewVersionPopup
component (where can I find this code?). When a new version is detected, a popup is shown:
componentDidMount() {
const { showPopup, goToPreviousHeaderState, device } = this.props;
// ...
if ('serviceWorker' in navigator) {
navigator.serviceWorker.addEventListener('controllerchange', () => {
showPopup({
title: __('New version available!')
});
// ...
});
}
}
Instead of displaying a popup that asks the user to refresh the page, you can automatically refresh it whenever there is an update
Pros:
Cons:
To implement this, override the NewVersionPopup
component.
scandipwa override component NewVersionPopup
After copying the original componentDidMount
function to override it, remove the code that displays the notification, and instead immediately refresh:
componentDidMount() {
// ...
if ('serviceWorker' in navigator) {
navigator.serviceWorker.addEventListener('controllerchange', () => {
window.location.reload();
});
}
}
Instead of displaying a popup, the cache is invalidated. For the current page visit, the old version will be still used. However, the new version will be fetched when the user visits the page the next time.
Pros:
Cons:
Override the componentDidMount
function to do nothing:
componentDidMount() {}