Professional Documents
Culture Documents
It has the ability to intercept network requests, modify them and redirect
them; it is quite powerful. The service worker’s main function is to serve a
cached/stored version of your application when the network is down. This
makes them suitable for making your website work o ine.
1. When your site loads in the browser, the service worker nds all the les
you speci cally tell it to store, downloads them and then stores them in a
space in the browser known as the cache. You can store anything from
images, videos, html les, icons etc. These les should be les needed by
your website or web page to function.
But there’s a catch, if any one of the les you speci ed fails to download,
the installation process fails, then your service worker won’t be activated.
On the other hand, if all the les are successfully downloaded, the service
worker can then be activated. This phase is called the installation phase.
2. Then, when a visitor visits your web app for the rst time, the service-
worker from your site goes through the installation phase on their
computer. On subsequent visits to your website, if same visitor loses
internet connection, the service worker picks up on this and reaches into
the browser storage for the les previously downloaded in the installation
phase and displays your website. This is called the fetching phase
This API is quite exciting and powerful. If you feel like you could use this and
you are not a developer, it is best to consult one and discuss the
merits/demerits and how it could work for your web application. On the
other hand, if you are a developer, I have some code samples we can go
through as to how to go about implementing the o ine experience.
You also need to clone the code repository I’ll be demonstrating with, by doing
git clone
https://github.com/AdeyinkaAdegbenro/Javascript_Calculator.git
JavaScript_Calculator
→index.html
→readme.MD
→style.css
→script.js
app = Flask(__name__)
@app.route('/index')
def home():
return render_template('index.html')
@app.route('/sw.js', methods=['GET'])
def sw():
return app.send_static_file('sw.js')
app.run(debug=True)
• Create a folder named templates . Move index.html from the root folder
to the templates folder. We are moving index.html because ask serves
its html les from the templates folder by default.
• Since we have moved the positions of our static les, we have to update
their paths in the script tags in index.html . Open templates/index.html,
and on lines 3 and 12 change style.css to /static/style.css and
script.js to /static/script.js respectively. At the end of the day we
have something like this:
our new templates/index.html
JavaScript_Calculator
→server.py
→readme.MD
→templates
→→index.html
→static
→ →style.css
→ →script.js
Create a le named sw.js and then place it in the static directory. Then go to
static/script.js and enter the following at the bottom
if ('serviceWorker' in navigator) {
// we are checking here to see if the browser supports the
service worker api
window.addEventListener('load', function() {
navigator.serviceWorker.register('../sw.js').then(function(registr
ation) {
// Registration was successful
console.log('Service Worker registration was successful with
scope: ', registration.scope);
}, function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
});
}
The line
navigator.serviceWorker.register('../sw.js').then(function(registrati
on...
is the main code that does the registration of our service worker script.
The register method takes the url of our sw.js script. Remember, in our
Flask le server.py , we created a route that tells Flask to nd the le for url
/sw.js in /static/sw.js ; we have to tell our script.js le how to nd our
sw.js le. We do this by pre xing the url /sw.js with a .. , which is
basically telling the browser to change the directory a step back (from the
static folder to the root folder) and call sw.js . Now visit http://localhost:5000
in your browser and open your console. You should see this:
Also, chrome has made it very easy to debug service workers by providing the
application tab in the console. Visit the console by doing ctrl shift i . If
you visit the application tab, you see this:
This comes in handy while trying to monitor/debug our service worker script.
If you click the little blue sw.js in your browser, it is going to take you to the
empty source of our sw.js le. It is empty because we have not added any code
to it.
self.addEventListener('install', function(event) {
// install files needed offline
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
The code above handles the installation phase of the service worker script.
What we did is this, we are asking the script to install the urls needed for the
calculator to work. They include ‘/’, ‘/static/style.css’,
‘/static/script.js’. Urls ‘/’ and ‘/index’ are the routes that serve our
index.html le. You can con rm this by checking server.py . So ultimately,
all we are doing is saving les returned by each route/path in the browser
cache. o ine-calculator is the name of the cache where we are asking the
script to store our les in the browser. So think of it as storing les the browser
would normally request from the server in the browser. This way, when
there’s a network issue, the browser can serve your web app’s les from its
own storage without the internet. Sort of like downloading movies to your sd
card so you don’t have to stream them every time.
Make sure your server is running using python server.py. Then navigate to
http://localhost:5000/. Also, make sure your console is open. In your console,
visit the Application tab. You should see the o ine-calculator cache in the
cache storage section:
When you click the o ine-calculator line, you should see the les that have
been cached:
Now that we have con rmed that our les have been cached in the browser,
it’s time to go o ine. Oh wait, we can’t. Reason — if we go o ine now, the
script does not know how to retrieve our les to show the user. You have to
teach it how. That’s where the fetch handler comes in.
self.addEventListener('fetch', function(event) {
// every request from our site, passes through the fetch handler
// I have proof
console.log('I am a request with url:',
event.request.clone().url)
event.respondWith(
// check all the caches in the browser and find
// out whether our request is in any of them
caches.match(event.request)
.then(function(response) {
if (response) {
// if we are here, that means there's a match
//return the response stored in browser
return response;
}
// no match in cache, use the network instead
return fetch(event.request);
}
)
);
});
What we have done here is set a fetch event listener. The listener well, listens
for any form of web request and then checks if the request is stored in our
browser cache. If it is, the response is gotten from the le stored in the cache.
If however, the request was not found, then we just
do fetch(event.request) . Which is equivalent to how the browser will get
the request normally.
For a better understanding of how the fetch and cache API works, study
these resources, cache and fetch.
It is time to reload our page. Reload it once to update the script. And then,
shut down the ask server, and also put your computer in airplane mode.
Now after reloading the page again, I get this
We have our page loading o ine alright. Except our calculator does not seem
to be working. From my console, I can see the fetch event for
var urlsToCache = [
'/',
'/static/style.css',
'/static/script.js',
'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.j
s'
];
Now we go back online and reload our page (don’t forget to start your server up
again), and then go o ine again (shut your server down too) . After reloading
my page, I get this
Tada!
Since we added the jquery url to our list of urls to cache, our calculator can
now work o ine. Also, the cache has been updated with the jquery url
Jquery in Cache storage
We now have a working calculator o ine. You can nd the before and after
code on github.
While this tutorial might look easy, this is not all there is to know about
service workers. There’s more, but I wanted to introduce you to the most fun
part rst, so you won’t get bored. Here are other topics and resources (in no
particular order) you should look into, if you want to dive deeper into service
workers and fully understand how they work
1. https://developers.google.com/web/fundamentals/primers/service-
workers/
4. https://developer.mozilla.org/en-US/docs/Web/API/Cache
5. https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
Ciao.
371 5
Write a response…
Hafiz Adewuyi
Mar 29
I like that you use type instead of copy and paste. I’ve read from multiple
sources that a major part of learning when you’re following along with
already-written code is to type it out line-by-line.
Hafiz Adewuyi
Mar 29
For clarity, it should be speci ed that this code should also be included in the
sw.js le (remember we also have script.js), just below the rst block of code.
6 1 response
Adeyinka Adegbenro
Mar 29
Yunfan
Mar 23
interesting, will `cache` share the limitation with other browser side storage
system like sessionstorage?
1 response
Adeyinka Adegbenro
Mar 23
Unlike session storage, cache storage does not expire per session unless you
explicitly delete it. The only limitation with cache storage is that each browser
has a limit on the amount of cache storage an origin can use. If you exceed
that limit, the browser can delete your cache. There’s an api, StorageEstimate,
one can use it to check the available space for your origin.
Hafiz Adewuyi
Mar 29 · 1 min read
When I rst loaded my website after including the service worker registration
code, I got the error: “Invalid MIME type: text/plain”.
Read more…
1 response
Adeyinka Adegbenro
Mar 29
Hafiz Adewuyi
Mar 29
change the directory a step back (from the static folder to the root
folder) and call sw.js
Why does the browser need to take a step back when the sw.js le is in the
same folder as the script.js le?
1 response
Adeyinka Adegbenro
Mar 31
The reason I made the browser take a step back is because our server (Flask)
which handles browser requests recognizes the /sw.js route as a le in the
static folder. Remember in server.py, we created a route to serve sw.js.
1 response
Hafiz Adewuyi
Mar 31 · 1 min read
I see.
navigator.serviceWorker.register(‘/sw…
Read more…
3 1 response
Adeyinka Adegbenro
Apr 2