The desired user experience is to access information on the internet without interruptions.Unfortunately, even with high speed connectivity we still experience delays.
Let me explain briefly, to get the information we need on our screen we send requests over the network and wait for that response.But what if, just what if the network is busy, or there is a mis-configured proxy somewhere, or you can't access the internet for whatever reason, It could be anything really, and we have to wait for a very long time?
This can be frustrating for most users.
But there is a solution , Building Offline First
web Apps.
But How Do achieve Offline Experience ?
To achieve offline experience we need to take care of:
- Caching Assets. The browser stores static assets such as html,css,Images.Such that when needed next,they are fetched from the browser cache.Big deal when the network fails.
- Storing data on the client side.Html 5 came bearing good news with offline technologies such as Web Storage, indexed databases among others enabling you store data locally on the users device.
Application Cache
Application Cache (Warning: It is being deprecated)
tried resolving the caching by allowing you to specify the set of resources you'd like the browser to cache and enjoy offline browsing,Improved speed by caching resources locally
( no need for network trips), and reduced server load (the browser only downloads resources that have changed from the server.)
Useful when the user is disconnected from the network, but did it deliver its promise? read API is A douchbag
Service workers
Service worker is a script (javascript file), that the browser runs in the background, acting like a proxy between application and the network.
Service worker enable applications intercept requests and then modify response,cache those requests to improve performance and provide offline access to cached data which makes it reliable.
Service worker is a type of web worker,runs on a separate thread from the web pages and UI ,enabling them to work without an active browser session.
It has no access to DOM, instead Communicates with the pages through post message
,those pages can then manipulate DOM if needed.
It offers you complete control over your app behavior especially when network is unavailable or slow.
This kind of control is the reason service workers run only on https,to avoid man in the middle attacks,though an exception for local requests-not necessary during development
- The intended use is to create offline first experiences
- Intercept network requests and handle response based on network availability,
- Great benefits online when experiencing slow connection
- Allow access to push notification and background sync
Service workers let you handle network requests differently from caching.
Service worker revolves around recent WebAPI
- Fetch
A fetch event is fired when resource is requested over the network. Perform standard request i.e Offers us the ability to look in the cache before making network requests.Inside a service worker,allows for intercepting requests and then modify the content other than the object requested.Use
respondWith()
to tell the browser we will handle the requests - Cache API. Cache API is independent from network status or browser cache. It gives you control on how and when to cache.It will not update items in the cache unless explicitly requested.Items in cache do not expire, they are gone when you delete the old cache.
Service worker lifecycle
- Registration
- Install
- Activate
Registration
To use a service worker you must register and define its scope.
Registration will tell a browser the location of the service worker and start installing it on the background.
code to register Service worker placed in sw.js
navigator.serviceWorker.register('/sw.js').then(function(){
console.log('Registration worked!');
}).catch(function() {
console.log('Registration failed!');
});
};
A Service Worker returns a promise.If the Promise resolves,the registration is successful otherwise the registration of the new service worker failed.
Browser Support
Since some browsers don't support service workers yet Is Service Worker Ready,perform a feature check by wrapping the service worker in an if statement
.
if (!navigator.serviceWorker) return;
navigator.serviceWorker.register('/sw.js').then(function() {
console.log('Registration worked!');
}).catch(function() {
console.log('Registration failed!');
});
};
Scope
The scope define the pages that a service worker controls.The default scope is defined by the location of a service worker script.
This means if you register a service worker at the root folder,it is not necessary to define its scope because it controls all the pages.
navigator.serviceworker.register('/sw.js', {
scope: '/'
});
The browser wont re-register an existing service worker on call ,but return a promise for existing registration
Installation
Once the browser has registered the service worker,it is immediately downloaded
if the browser considers a service worker new either by
- The Service Worker has never been registered before. or
- You altered the Service Worker Script,byte differences.
install event
is fired.
This is a perfect opportunity to fetch for resources that make the application shell from the network and cache them.Ideal for the static resources that our site depends on such as Html,Css,Fonts, Javascript etc.
If there is a previous version of service worker already running, it will still continue to serve pages.
The browser wont let the new service worker take control until the installation phase is complete.Instead it becomes the next version in waiting .
To delay the installation process and determine its success,we pass a promise to event.waitUntill
method.
If the promise resolves,the browser knows the Installation has completed.If it fails,well then it is discarded.No cause of alarm because the previous version of the service worker is still working.
This ensures only one version of your script is running at any given time.
self.addEventListener('install', function(event) {
event.waitUntil(
);
});
Activation
Once a service worker has successfully completed the installation phase,it enters activation stage.
In the case of the browser first encounter with a Service Worker, the service worker becomes active upon successfully completing the installation phase and will be able to control new page loads.However,It cannot control pages that were already loaded.To control the already loaded pages,a reload is required.
In the case where the service worker is updated, (Not the browser first time interacting with a service worker ), the newly installed service worker cannot take control until all the pages the previously installed service worker are closed.
Once all pages using the old (previously installed) service worker are gone,the new one activates,firing an activate event.
you can take control of of uncontrolled pages by calling
clients.claim()
within your service worker once its activated
self.addEventListener('activate', function(event){
});
Since the previous version is out of the way,it is a perfect time to delete the old cache so that all users can have the current version of our site.
gotcha
We change files all the time! When we make changes in our file say a css file, this can become a 'problem' .A page reload wont help much because we still using the cache with the old css.
Despite the changes in our css file,our site remain the same.Meaning, to see the changes, we make a change to the service worker script,you can simply add a comment ,remember its just a byte difference and the browser will consider it as 'new'
Notes
- Service workers does not provide cached data for offline use only,but also effective during slow connectivity online.
- Service workers are programmable JavaScript "servants/workers"
- They can not access DOM directly,instead communicate with the pages it controls through responding to messages via
postmessage
. - Require sites to be served over https. This is important because they intercepts request and can modify response ,to avoid hijacking by third parties
- Stays idle when not in use,restarted when next needed
- Make extensive use of promises
Further reading:
Conclusion
Thank you for reading, hope you are ready to give users an amazing experience both online and offline.Let me know if liked the article or if I missed something!
Top comments (4)
Thanks for the elaboration 🙌🙌🙌by tha you're the only fellow Kenyan I've seen on Dev community!
Glad to meet you fam 🇰🇪
Must read
Hello mate, thanks for sharing! do you have any example using storage from service worker?