Jagat Jeevan Sahoo
UI Developer @ThoughtWorks A tech enthusiast
Progressive web apps are normal websites that harness the app power to serve offline, cache data for better user experience, deserves to be on home screen for quicker accessibility, increases engagement with user through notifications, etc.
Prior to promises, there were callbacks. If not managed properly, added quite some of the spaghetti code and usually not very good to read.
let doSomething = function() {
if(error) return error;
onceDoneDoThis() {
ThenDoThisAfterFinish() {
...
}
}
}
Nodejs is non-blocking for I/O operations, but not good for CPU intensive work.
let loadData = function() {
return new Promise(function(resolved, rejected) {
request('someUrl', function(err, userInfo))
if(err) {
return rejected(err);
}
return resolved(userInfo);
});
}
Promise
Pending
Resolved
Rejected
let fetchData = request('url'); // This returns a promise.
fetchData
.then(addDataToUI)
.then(addFunctionalityToUI)
.catch(showErrorToUI)
A promise would always be settled through a resolve or a reject. So in the above example, even though "addDataToUI" fails it would continue. The value from the last promise would continue to the next then.
Since JavaScript is single threaded, any UI manipulation on the DOM would block the user interacting with the page.
Service worker can be compared to a browser thread which free-ups DOM interaction. Service worker cannot directly manipulate the DOM but can listen to the events and updates the events.
Example of a service worker where it executes.
SW
Install
Error
Activated
to be updated
Idle
Fetch/ Message
Terminated
SW gets terminated when not in use and again spins-up when required.
// Check if service worker is supported in browser.
if('serviceWorker' in navigator) {
navigator.serviceWorker.register('pathToServiceWorker.js')
.then(function(sw) {
console.log("Service Worker registered successfully", sw);
})
.catch(function(error) {
console.log("Could not register SW");
})
} else {
console.log("Service Worker not supported in your browser");
}
Check if service worker is supported in browsers from here
In the page, I have deleted unnecessary cache which gets accumulated. Below is the part of code which does this.
Feel free to clone the repo and tweak.
self.addEventListener('activate', function(event) {
console.log('SW activated ', version, ' -> ', new Date().toLocaleString());
event.waitUntil(
caches.keys().then(function(keys) {
return Promise.all(
keys.filter(function(key) {
return key !== version;
}).map(function(key) {
return caches.delete(key);
}));
}));
});
Main component of PWA is app-like feel and not let the website crash without the internet. For that we need to cache contents and show them when not online.
Some commonly used patterns are :
Cache first approach
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(res) {
if(res) {
return res;
}
if(!navigator.onLine) {
return caches.match(new Request(offlineHtml));
}
return fetch(event.request);
}));
});
checks the cache, if not found, checks whether online, if not serves offline page, else go to network.
There are header tags which makes sure we update stale data. Those are ETag, Last Modified Date, Cache-control, max-age, etc which makes sure we update the stale data and cache.
Apart from file caching, we would also require data caching. If we can store data from page to page, then we can reduce calling the server for small data.
For this, we have localStorage, sessionStorage, indexedDB. Below is the example for indexedDB.
Apart from caching the content to give app like feel, we also need our users to come back to our sites to know about activity happening here. This can be done using a push notification. Below is an example of the same.
A list of things needs to be known to push a notification.
The above link would show if a browser version supports push api or not. Some resources are below :
Its always good to give information about the application if you want to make your user bookmark / place it to the home screen. Before using it, we can check if browser supports or not from the link below.
You just have to add a link tag to your manifest file in the head of the html.
<link rel=“manifest” href=“/manifest.webmanifest”>
Mime type is optional: application/manifest+json.
{
"name": "Music for Web Application",
"short_name": "Music",
"start_url": ".",
"display": "standalone",
"background_color": "#fff",
"description": "Searching web for music",
"icons": [{
"src": "images/touch/music168.png",
"sizes": "168x168",
"type": "image/png"
}, {
"src": "images/touch/music192.png",
"sizes": "192x192",
"type": "image/png"
}],
"related_applications": [{
"platform": "play",
"url": "https://play.google.com/store/apps/details?id=music"
}]
}
Feel free to clone it and play around with the colours and icons.
By Jagat Jeevan Sahoo
Things to know when you want to give app like feature to websites.