How To Use Service Workers in Javascript - DEV Community
How To Use Service Workers in Javascript - DEV Community
5 2
Progressive Webapps use service workers to make websites and webapps feel more like
the native apps users know and love on their phones. This article will give you an
introduction into the topic with some simple - to - follow code examples.
When clicking on the + - sign, the PWA will be installed and grants you offline-access to
devdocs.io
You should not mistake PWAs with desktop or native applications built with Electron.js
or Nativescript though - they do only run on the browser's context and have no access
to device specific APIs.
But even without using the full toolkit, service workers give you a high level of control
over what gets cached, improving app speed and lowering server-side pressure. As of
2021, they are also supported in all major browsers, making them well considerable for
production - ready apps.
can only be used in a https - context for security reasons (note that for development
localhost is also considered a secure domain)
run on a separate browser thread, therefor have no direct DOM - access.
run completely asynchronous and rely a lot on promises. In case you need a refresh,
I've got an article on promise basics here.
Project setup
You can of course follow freestyle, but I recommend you use the boilerplate from my
Github repository - it includes placeholders for the functions that are introduced in this
article, as well as some helper functions to create new elements on the DOM. If you just
want to jump into the source code, there's also a 'done' branch.
https://github.com/tq-bit/service-worker-basic-demo/tree/main
We will
Note that for each snippet below, there is a corresponding TODO - comment inside
each file that serves as a placeholder. If you somehow get lost, try and use the Todo
Tree VSCode plugin for quick navigation.
Heads up: Many other articles also cover a few lines of code to check if service
workers are supported by the browser. I've left this out on purpose, as most of the
modern browsers have a built-in support as of today.
Heads up: While you're here, make sure to toggle the Update on reload checkbox - it
makes sure that no data remains unintentionally cached.
Turns out that, once downloaded and activated, a service worker registration is created
inside the navigator.serviceWorker container and can be read out like this:
To round things up, add the following to your main.js file for user feedback:
// Query for the indicator DOM element and remove its classes
const indicator = dqs('#worker-indicator');
indicator.classList.remove('bg-danger', 'bg-success');
Finally, hook the method up to the sw-toggle event that is fired when registering and
unregistering happens (therefor the window.dispatchEvent ):
Back to your app, the image below now shows an active service worker instance.
Once you click on Unregister , you can also monitor the change in your devtools
In case of manual registration / un-registration via the button, you might have to
refresh your browser once to activate the service worker. In a productive scenario,
this step should be taken by the website's / app's lifecycle methods
That wraps up how to handle registration and also what we want to do within our
main.js file. Let's now take a look inside the serviceworker.js file.
Note that, since a service worker will only work over https or from the localhost, you
will need a development server to serve your files. If you're using VSCode, try the Live
Server extension.
Inside the service worker file, the same provides us functions and properties such as
self or caches . These we can utilize to enforce the service worker magic.
// appActive indicates the currently active cache, or more specific the name
// of the cache used by the application. This variable should be synchronized
// with appWhitelist and fit the latest app version.
const appActive = 'app_v1';
// appFiles holds the path to files that should be cached for offline usage
const appFiles = ['./index.html', './main.css', './main.js'];
In case you do not want to handle these strategies yourself, there are a few handy
javascript libraries that can help you out, such as workbox-sw.
While we are at it, let's also add a function to get rid of old caches. Like this, we can
make sure that only the current relevant cache is active and no old files will get in the
way and cause inconsistencies.
Then, once a new service worker is installing, call this function. the event.waitUntil -
method makes sure the above function resolves before moving ahead in the code. After
installation, the files will then be cached and ready for offline usage.
And that's about it - the defined files are now available within the service worker's
cache.
3.4 Accessing cached content
The above makes sure our caching strategy is being enforced, but does not yet give us
access to the files or data being stored. To gain access, our service worker has to listen
to outgoing http-requests and then - based on our caching strategy - either return a
cached response or fetch the data from the remote location.
Let us first add the necessary event listener. Add the following to your serviceworker.js
- file
As you see, cacheRequest takes in two arguments - the active version of the cache, as
well as the outgoing request from the client to the server. It is meant to return a
response that can be resolved as if there was no middleman involved. Therefor, before
we write the code, let us first define what exactly is meant to happen.
1. Check all active service worker caches (not just the currently active one, but all!) for
an already cached response.
2. If it exists, return it - no network communication happens and the http-request
resolves. If it does not exist, move ahead.
3. Check if the user is online (via navigator.onLine property)
4. If user is online, execute the fetch-request. When it resolves, clone the raw response
and put it into the currently active service worker cache (not all, just the currently
active one!). Also, returns response to the calling function
5. If user is offline and no cached content is available, log an error to the console.
At this point, I'd like to state that a carefully chosen caching-strategy in step 3.1 is key to
properly handle these interceptions.
In the described case, a static file's version that has been cached in app_v1 will still be
fetched in app_v2 if the app_v1 still remains in the appWhitelist array. This will cause
problems if the initial file is outdated.
Now, to wrap caching up, add the following to your serviceworker.js - file
const cacheRequest = async (appActive, request) => {
const online = navigator.onLine;
Don't take my word for it though - try it out yourself. Below, I'll link you the final Github
branch so even if you didn't follow every single step, you can get your hands dirty and
try an offline-first approach. If you'd just like to take a glimpse into the functionality of
this article's proof of concept, I've also added some screenshots for that under 4.
Working samples.
https://github.com/tq-bit/service-worker-basic-demo/tree/done
So what are you waiting for? Clone down that repos and start coding.
4. Working samples
4.1 Lifecycle and exercising caching strategies
Assume you just deployed your service worker app or release a new app (and therefor a
new cache) - version, your service worker will do the necessary setup during installation:
A new service worker will always clean up old versions that are not whitelisted and make
sure the static files are available before the first fetch request. Note how it conveniently
caches the bootstrap css I'm using for the styling.
Get started
Auth0 PROMOTED
Easy to implement, endless possibilities
With a few lines of code, you can have Auth0 by Okta integrated in any app
written in any language and any framework. 🚀 Start building for free today.
Sign up now
tq-bit
I'm a selftaught (web) developer. On sunny days, you can find me hiking through the Teutoburg
Forest, on rainy days coding or with a good fiction novel in hand.
LOCATION
Bielefeld, Germany
WORK
Developer @ CPro IoT Connect
JOINED
Dec 21, 2020
How to use IndexedDB to store images and other files in your browser
#javascript #webdev #database #tutorial
Arm PROMOTED
Stay Ahead with Cloud-Native Insights
💪 Save resources and build scalable and efficient cloud-native apps.
Register Now