When it comes to Progressive Web App (PWA), it confuses a lot of beginners into thinking that “it needs some kind of special advanced programming”. Actually, PWA is just a “regular web app with some additional stuff”. A quick quote from Wikipedia:
A progressive web application (PWA), or progressive web app, is a type of web app that can be installed on a device as a standalone application. PWAs are installed using the offline cache of the device’s web browser.
So, a summary on “how to create a PWA”:
- Develop your web app as usual.
- Make it installable.
- Offer offline capabilities.
Yep, that’s all. Let’s walk through a simple “Hello PWA” example.
CODE DOWNLOAD
I have released this under the MIT license, feel free to use it in your own project – Personal or commercial. Some form of credits will be nice though. 🙂
VIDEO TUTORIAL
PART 1) DUMMY WEB APP
The first step to building a PWA, is to develop your web app as usual. For this example, we will create a dummy page with the usual HTML CSS JS and throw in an image.
<!DOCTYPE html>
<html lang="en">
<head>
<!-- (A) "USUAL STUFF" -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dummy page</title>
<link rel="stylesheet" type="text/css" href="1-dummy.css">
<script src="1-dummy.js" defer async></script>
</head>
<body>
<h1>Hello World!</h1>
<img src="NOT.webp" loading="lazy">
</body>
</html>
/* DUMMY STYLE */
* {
font-family: Arial, Helvetica, sans-serif;
box-sizing: border-box;
}
var itworks = document.createElement("div");
itworks.innerHTML = "JS WORKS";
document.body.appendChild(itworks);
PART 2) INSTALLABLE WEB APP
The next step is to “make it installable”. How it is done is simple – Just define a web manifest file.
2A) MANIFEST META
<!-- (B) WEB APP MANIFEST -->
<link rel="manifest" href="2-manifest.json">
In the <head>
section of your web app, insert a link to the manifest file.
2B) WEB APP MANIFEST
{
"name": "Hello PWA",
"short_name": "Hello",
"icons": [{
"src": "FAVICON.webp",
"sizes": "512x512",
"type": "image/webp"
}],
"start_url": "1-dummy.html",
"scope": "/",
"display": "standalone",
"background_color": "white",
"theme_color": "white"
}
There are a lot of things we can define in the manifest file, I will highly recommend you read through the full list. In this example, let’s go through the basic ones:
name short_name
The name of your web app.icons
The icon of your web app. As you can see, we can define multiple icons with different dimensions and image formats… I am lazy here and only provided one. Feel to resize yours if you want, make it “look good on all kinds of screen sizes”.start_url
Which page to show on app launch.scope
The base path of where you deployed the app. Example,http://site.com/MYAPP/
or just/MYAPP/
.display
How the web app will look like.fullscreen
Launches in fullscreen mode.standalone
In a separate window.browser
As it is, in a browser tab/window.minimal_ui
A tab/window with minimal interface.
background_color theme_color
Self-explanatory.
PART 3) OFFLINE CAPABLE
The final step involves turning the app into capable of running offline. That is, saving your front end asset files into the user’s browser.
3A) REGISTER SERVICE WORKER
<!-- (C) SERVICE WORKER -->
<script>
if ("serviceWorker" in navigator) { navigator.serviceWorker.register("3-worker.js"); }
</script>
In the <head>
section of your web app, register a service worker.
3B) SERVICE WORKER
// (A) SAVE PROJECT FILES INTO BROWSER CACHE
self.addEventListener("install", evt => {
self.skipWaiting();
evt.waitUntil(
caches
.open("Hello")
.then(cache => cache.addAll([
"1-dummy.css",
"1-dummy.html",
"1-dummy.js",
"2-manifest.json",
"3-worker.js",
"FAVICON.webp",
"NOT.webp"
]))
.catch(e => console.error(e))
);
});
// (B) LOAD FILES FROM CACHE - FALLBACK TO NETWORK IF NECESSARY
self.addEventListener("fetch", evt => {
evt.respondWith(
caches
.match(evt.request)
.then(res => res || fetch(evt.request))
);
});
// (C) OPTIONAL - CLAIM CONTROL INSTANTLY
self.addEventListener("activate", evt => self.clients.claim());
A “service worker” is a piece of Javascript that runs in the background. In this one:
- Create a
Hello
cache in the user’s browser and save the necessary files. - “Hijack” the
fetch
events. Load the requested file from the cache, fallback to load from the network if the file is not in the cache. - Optional. Instantly activate the service worker.
Long story short, this is the mechanics of “offline mode”. Save and load the files direclty from the local browser cache.
THE END
Congratulations, you have created a barebones progressive web app. But of course, a “real progressive web app” is more than just a dummy page. To add “progressive” to your web app, you have to keep a couple of things in mind:
- PWA and Web 3.0 is about decentralization.
- That is, make web apps act like native installed apps.
- They will at least “show and do something”, even when the user is offline.
- As above, saving files into the user’s device is one way to offer offline capabilities.
There are a lot more to just “saving files” though. Going forward, I will recommend you check out the treasure trove of Web APIs. A few good ones to start with –
- Everything that deals with data storage – Storage, Storage Access, File, Indexed Database.
- Async, Fetch, Background Sync.
With that, I shall sign off now – Good luck with your project.