Bringing Service Workers to Magento2

I started playing around with service workers with magento2 platform. I could have started with Google code lab on Progressive web Apps but I was too excited to implement service workers in magento2. It kind of makes sense to take advantage of service workers for ecommerce websites. For me the most exciting feature of service workers is it’s ability to act like a proxy. You can modify request and responses. You can choose whether you want to serve the content from cache or network or mix em up. Pretty cool right!! The whole point is to increase perceived speed. But as always, whenever you wanna implement something absolutely new, you have to spend considerable time in setting the development environment. Service worker is no exception. Apart from that there are other things which might bug you for a while. Here’s my list of things to be aware about while working with service workers and magento 2.

1) Service workers run only in secure environment

Man! You have to either serve your local site from localhost or make https work locally. Like many other magento developers, my dev environment is served on domain mage.dev. I don’t like localhost/magento. So I’d to install ssl certificates on my local and make dev site fully HTTPS. This is what it should look like on your local if you are serving from a domain

HTTPS local development environment

Service worker registration will simply fail if you don’t have HTTPS for a custom domain. If HTTPS set up is too much of hassle for you, consider serving your site from localhost. If you want to setup https on local then this gist might come in handy. Setup for nginx and apache2 might differ a bit but they are two key points two remember. Generate ssl certificate with SAN and use command like

sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /etc/apache2/ssl/localhost.crt

I did this on my mac machine but shouldn’t be very different on linux. Your browser will start trusting the certificate authority after you run this command.

2) Allowing more scope with Service-Worker-Allowed header.

I use nginx on my local dev so I added following header in my nginx.conf such that

add_header Service-Worker-Allowed “/”;

when I review service worker script request in my devtools network panel, I see that header above in response headers.

This way I’ve changed scope of my service worker from domain.com/script/path/service-worker.js to domain.com/. So keep that header in your toolbox.

3) Service workers are fully asynchronous

4) Service workers don’t have access to DOM or localStorage.

Service workers excute in a separate thread and a separate context. Generally, the javascript we ship with our sites have window object as top level scope. Service workers, on the other hand, have their own context called “ServiceWorkerGlobalscope”. You will often come across something like this:

this.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});

this keyword here refers to Service worker global context. An interesting thing to note about chrome devtools is how it allows us to play around in a particular context. Let’s say you wanted to see what all functions are available in window context and what all are available in service worker context, this is how you inspect that.

Selecting service worker scope

This scope is available in drop down once your service worker is installed.

Service worker global context

Notice the pink highlighted dropdown at top left corner. Any javascript we execute in console now executes in service worker context. To switch back to window context, just select the “Top” as scope.

5) location.href does not refer to URL of existing page

To some of you it might seem like obvious but I missed it. location.href in service worker scope points to service worker url. This is useful in a way if you want to other service workers supporting scripts using importScripts() function. That way you don’t have to worry about version part of magento 2 URL’s.

6) magento-x-init means your script will load after page load

This is easy to forget. I had following snippet in my registration script

if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/service-worker.js');
});
}

This registers service worker when document load is finished. This works perfectly if you directly include this in a script tag but I was calling this code via x-magento-init as folllows:

<script type="text/x-magento-init">
{
"*": {
"Humcommerce_WebApp/js/registration": {
"swUrl":"<?php echo $serviceWorker?>"
}
}
}
</script>

Standard magento 2 way right? This is run only a little after document load. So you don’t need window.addEventListener(‘load’,callback) part of the equation.

Finally I’ve been working on an extension for magento2 that adds pwa capability to magento 2. Take a look at https://github.com/humcommerce/module-pwa . It’s still work in progress so please leave your suggestions below or on github issues section.

--

--

--

Dive deep into the amazing world of e-commerce. Explore different aspects of the Magento universe with opinions, news roundups and tutorials with us.

Recommended from Medium

Scope Creep In Software Development

Latest WSEDAO dApp update

How much Dart is required to get started with Flutter development?

Semantic Versioning in Gitlab

Easily Find the Meaning of Words You Come across on Web

How I Made a Smart Mirror that Integrates with Google Drive

The Hollywood Principle: A Guide to Libraries vs Frameworks

The Death of microservices — Distributed Monolith 101

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Abhishek Jakhotiya

Abhishek Jakhotiya

just a bug hunter and problem addict

More from Medium

TravelPerk App system

Team Page Redesign — Redefining Corporate Hierarchy

One API call to insert in multiple tables Supabase

Building a Ruby on Rails API