The Blog as a PWA
What is PWA
PWA is short for Progressive Web Applications. If you want to learn more about the basics of PWA, go check the Google PWA official website.
Also, I did a brief intro to PWA in the CORP as tech share a while before. The content mainly comes from the PWA official site and the offline cookbook. Check it out if you desire.
Apply PWA Features to The Blog
I want to apply these beautiful PWA features to the blog, so that I can add the app to my home screen and browse the blogs offline. Now, let’s go through how to do that step-by-step.
First of all, Generate the Service Worker JavaScript
-
I need to generate the Service Worker JavaScript,
sw.js
, with all my content and pre-cache the pages into the cache. This way, when service worker is installed, everything has been pre-cached. It will enable the full off-line mode by all the pre-cached files. This is the so-called install step of PWA life-circle.const cacheName = 'sr-precache-##REVISION##'; const PrecacheList = ##PRECACHE_LIST##; self.addEventListener('install', function(e) { console.log('[SW] Install'); e.waitUntil( caches.open(cacheName).then(function(cache) { console.log('[SW] Caching all files.'); cache.addAll(PrecacheList); console.log('[SW] SkipWaiting'); return self.skipWaiting(); }) ); });
There will be a post-build script to replace
##PRECACHE_LIST##
with the files in mypublic
folder after I generated my site. The script will also replace##REVISION##
with the git sha oforigin/master
.Also, as you can see, there is a command
self.skipWaiting()
to tell SW to skip waiting, meaning the service worker activates as soon as it’s finished installing, even for updating. -
Then, I would want SW to use these pre-cached files for the requests. So I added lines to customize the fetch event in
sw.js
.self.addEventListener('fetch', function(e) { e.respondWith( caches.match(e.request).then(function(response) { return response || fetch(e.request); }) ); });
This is a very basic cache strategy, serving from cache and then network, a.k.a, cache-first.
-
After the steps above, the web app now works when offline. However, there are still issues.
- The cache will be invalid after I update the site, I need to remove the invalid cache.
- SW will wait for all the tabs to close so that the new
sw.js
could apply to the tabs.
So, I need to update the activate step so that I can fix these issues.
self.addEventListener('activate', function(e) { console.log('[SW] Activate'); e.waitUntil( caches.keys().then(function(keyList) { return Promise.all(keyList.map(function(key) { if (key !== cacheName) { console.log('[SW] Removing old cache', key); return caches.delete(key); } })); }) ); return self.clients.claim(); });
Since every update will change the git sha, I will get a unique new sha whenever there is an update. Then I just need to delete caches which is not the latest one.
Also, with
self.clients.claim()
, I can take control of uncontrolled clients/tabs within my service worker once it’s activated.
With all these steps above, the basic sw.js
is initialized.
Let’s Register The Service Worker JavaScript
It’s easy to do this. Just test the browser to see if it supports SW, and register if so.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').then(function(){
console.log('Service Worker Registered');
});
}
Create The Web App Manifest
The web app manifest is a simple JSON file that tells the browser about your web application and how it should behave when ‘installed’ on the user’s mobile device or desktop. Having a manifest is required by Chrome to show the Add to Home Screen prompt.
- Add
name
&short_name
- The
name
is used in the Add to Home Screen prompt, while theshort_name
is used as the app name after being added to home screen.
- The
- Add Icons
- Ah.. I just used the
Preview
app on Mac to create my PNG icons.
- Ah.. I just used the
- Add
start_url
&scope
- The
start_url
is the url when the app is launched as a fresh start after being added to home screen.
- The
- Add
backgrou_color
&theme_color
- These two will affect the Android Chrome header color and the app splash screen after being added to home screen.
- Add
display
- If you want the immersive experience, try
standalone
(with only status bar) or evenfullscreen
(no status bar).
- If you want the immersive experience, try
Now, let’s register this configuration file in the <head>
tag of all the pages.
<link rel="manifest" href="/manifest.json">
It is NOT Enough, Yet
-
For iOS
As we all know, PWA is not an Android only feature, it also works on iOS with iOS 11.3. However, you can barely find it on iOS 11.3 release notes, even Google says PWA is firstly introduced by Steve Jobs. And in this medium post, there are a huge ton of useful information about PWA on iOS.
- The Icons for iOS
- If you are looking for Apple official doc, here it goes.
- The Splash Screen for iOS
- Check more details here
- Splash Screen Genertor
- Status Bar Style
- More details here
Why Google and Apple always do the same thing in a different way? And why Google is doing the standard way and Apple is doing the non-standard way? (Or, at least Google is making his way the standard way. This is the reason why we need to be open, instead of locking ourselves into a cage which looks big, but will become smaller and smaller.)
- The Icons for iOS
-
Client Tracking
With Google Analytics, I can track my blog visits very easily. Google has done really nice shits. (PWA is one of the shits!)
-
Local Dev
Actually, when you initialized the PWA, you don’t need it for dev mode when writing posts or updating blog styles. The cache will breake some functions of the auto-reload logic.
Conclusion
So, here it comes, the PWA for the blog.
PWA is going to change rules of the game, hopefully, if and only if it will be more and more improved and applied. And it did really pushing the web to the next milestone.
PS:
This is not a post to praise Google. Actually, Apple is also doing great. A lot of people love iPhones. BTW, I love Mac. Even Microsoft is trying its best to serve bests apps on iOS/Android, when WinPhone has been dying.
I mean, every company has its good side, and bad side as well. Maybe they are saying “don’t be evil”, while they are doing the evilest things.