This post was originally published on silvestar.codes.
As of today, my site is available as a Progressive Web App. Yaay! 💯
In this post, you would learn more about how and why I added this exciting feature to my site.
Why did I do it
I like to think of myself as a very pedantic person, and I was trying to make my site better from the very first day. At the time when I was building my site, I didn’t understand all metrics from web performance tools like PageSpeed Insights or WebPageTest. But, as I was trying to make my site better, I was learning new techniques, and my website got better and better.
Now my site gets top scores, but one thing was bothering me for some time. It was the Progressive Web App score.
By looking at the PWA report, I realised my site is ready for PWA. There were only a few issues to resolve. I didn’t understand these issues, but that never stopped me before.
How I did it
As my starting point, I decided to follow the “Your First Progressive Web App” tutorial. The very first step was to update my webmanifest.json
file. I added start_url
and display
options and some required meta tags, like <meta name="apple-mobile-web-app-capable" content="yes">
.
{
"name": "SB site - Silvestar Bistrović website",
"short_name": "SB site - Silvestar Bistrović website",
"icons": [
…
],
"theme_color": "#12e09f",
"background_color": "#fff",
"start_url": "/offline.html",
"display": "standalone"
}
Next, I created sw.js
file for Service Worker. To register service worker, there is a small snippet that needs to be added to your index page:
// CODELAB: Register service worker.
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then((reg) => {
console.log('Service worker registered.', reg);
});
});
}
The content of the Service Worker file could vary, depending what you want to use achieve with your site. Since my site is quite straightforward, I decided to make use of basic offline experience only. That means I needed an offline.html
file for offline experience. It would be a stripped version of my homepage. So I removed external images, and created a placeholder using CSS. I removed external CSS file and inlined it in head
section. The only thing left to do was to add favicon files. I am not yet sure if this is need, but I decided to put it there, just in case. Those files aren’t big anyway.
The sw.js
file could be broken into four segments:
- defining constants,
- installation,
- activation, and
- fetching.
First, I defined the cache name and which files to cache.
// constants
const CACHE_NAME = 'sb-cache-v1.3'
const FILES_TO_CACHE = [
'/offline.html',
'/favicon/apple-touch-icon.png',
'/favicon/favicon-32x32.png',
'/favicon/favicon-16x16.png',
'/favicon/site.webmanifest',
'/favicon/safari-pinned-tab.svg',
'/favicon/favicon.ico',
'/favicon/mstile-144x144.png',
'/favicon/browserconfig.xml'
]
Next, I created the install
event which opens cache with given cache name and caches the files.
self.addEventListener('install', (event) => {
// CODELAB: Precache static resources here.
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
console.log('[ServiceWorker] Pre-caching offline page')
return cache.addAll(FILES_TO_CACHE)
})
)
})
After that, I created the activate
event, which cleans cached files from disk.
self.addEventListener('activate', (event) => {
// CODELAB: Remove previous cached data from disk.
event.waitUntil(
caches.keys().then(keyList => Promise.all(keyList.map((key) => {
if (key !== CACHE_NAME) {
console.log('[ServiceWorker] Removing old cache', key)
return caches.delete(key)
}
})))
)
})
Finally, I created the fetch
event, which handles page navigations only when request .mode
is navigate
. If the request fails to fetch the item from the network, it tries to fetch the offline.html
file.
self.addEventListener('fetch', (event) => {
// CODELAB: Add fetch event handler here.
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request)
.catch(() => caches.open(CACHE_NAME)
.then(cache => cache.match('offline.html')))
)
}
})
Final Results
After the deployment, I run the audit for the site and now I have it looks like this:
I think fireworks deserve another appearance. 💯
Next steps
The next steps are to learn more about Workbox. And after that, I plan to add full offline experience for my side project Code Line Daily.
Edit: Continue reading my second article about “How I built my second Progressive Web App (PWA)”.
Top comments (8)
Nice article...
When I tried out PWA for the first time it felt like a lot of configuration to do but workbox makes this task very easy.
I used it with create-react-app which has a default setup for workbox but in order to customize the workbox config I used react-app-rewired which lets you override webpack config with your custom configuration & attach your custom service-worker file.
Here I used StaleWhileRevalidate strategy.
This was a simple weather app where I was caching the bundle files, app background images, favicon icon. And I was storing location data, weather API response data in localStorage for offline access if the network fetch call fails...
Finally, I was able to achieve those scores in my app as well...
Source code: github.com/rajatkantinandi/weather...
Live link: WeatHere.now.sh
Very nice. Thanks for sharing!
Can you make a blog post on how to do it on react.js
You mean, how to make React.js app as Progressive Web App?
The answer is no, I have never learned React.js.
okay
See this comment from Rajat: dev.to/rajatkantinandi/comment/i9l1.
Can you please?
See this comment from Rajat: dev.to/rajatkantinandi/comment/i9l1.