Introduction, audience, and scope

This is a very, very basic tutorial. I will refrain from even calling it ‘bare-bones’ because that skeleton would be missing the metacarpals and a femur, so to speak.





The goal, or use case, is simply to get the app to pass the PWA audit in Chrome and make the app downloadable to a user’s machine, should the user decide they are better off using an offline version of the application.





To begin with, you should already have written and fully debugged a dirt-simple, front-end only HTML/JavaScript app that does not require any external resources (it does not connect to an API for data, for example).





To see the example I used, go to here





Besides some basic HTML and JavaScript, some introductory knowledge of service workers is a prerequisite for this tutorial. PWA is where you will really start of suffer from and then master service workers. If you are absolutely new to service workers, stop here and go do one or two tutorials that are focused just on service workers. Then come back.





Please note that I am using a Windows 10 machine and the Chrome browser for all of this. If you are following the steps of this tutorial and getting different results, first check to see if the issue may be that you are using a different setup.

Make your app visible to Chrome

I am using Chrome’s Audit feature to get started on the PWA version of the app (Audit comes with Chrome - just open Chrome and hit F12 to see the dev tools; Audits is one of the tabs across the top). In order for Audit to see your app, and then later for service workers to function properly, your app has to be in a HTTP/HTTPS document. You cannot just be running your app on local host. There’s probably half a dozen better ways to go about meeting this requirements, but what I did to accomplish this was just to host my app on GitHUB pages.





(For more of a nuts and bolts guide to actually setting up a GitHub Pages website manually without all the bells and whistles, go to my earlier post ).





NOTE: If you opt for GitHub pages, always use full reference paths as opposed to partial paths. Absolutely make sure to name the main file “index.html” or GitHub Pages won’t work in your browser.

Audit your app and clean up failures

Once you have reached the point where you can view your app the in Chrome web browser as a HTTP/HTTPS doc, you are ready to run an audit in Chrome and figure out where to go from here.

Click F12 and that will open the Chrome dev tools. Up at the top where it says “Elements,” “Console,” “Sources,” etc,. click on the “Audit” tab. On the “Audit” tab, click the “Generate report” button.

There will probably be lotsa red telling you how miserably your site fails to meet basic industry standards.





At this point you could easily ignore the components of the Audit that do not have to do directly with PWA and just move on. But loose ends drive me batty so I cleaned them up. Just google each statement and patch up your HTML accordingly.

Add a manifest.json file

PWA requires a ‘manifest.json’ file in the root directory. You have to title the manifest ‘manifest.json’ and save it as a .json file.





The manifest you are starting out with in this tutorial is very minimal. Other more advanced tutorials will show you how to do more with the manifest and more with logos. For now we are just keeping things dirt-simple.





Your manifest should look like this (fill in what you want for ‘name,’ ‘short_name,’ and the colors):



{

"name": "<the name of your app>",

"short_name": "<the name of your app>",",

"icons": [

{

"src": “images/192_icon.png",

"type": "image/png",

"sizes": "192x192"

},

{

"src": "images/512_icon.png",

"type": "image/png",

"sizes": "512x512"

}

],

"start_url": "https://<username>.github.io/index.html",

"display": "standalone",

"background_color": "<the color you want>",

"theme_color": "<the color you want>"

} "name": " ","short_name": " ",","icons": ["src": “images/192_icon.png","type": "image/png","sizes": "192x192"},"src": "images/512_icon.png","type": "image/png","sizes": "512x512"],"start_url": "https:// .github.io/index.html","display": "standalone","background_color": " ","theme_color": " "

Create an offline version of the app

Just create a copy of the index.html file in the root directory. Title this new file ‘offlineApp.html.’

In a full PWA application, something that is beyond the scope of this tutorial, the offline version of the app is part of what allows PWA to turn your app into something that can seamlessly transition between an online and an off-line experience. It's a big deal. But given the very limited scope of this tutorial, just create and rename the copy of index.html for now. Consider it a stub where the future offline version of the app will go when you know more about PWA.

Create the Service Worker

Now, create the service-worker.js file in the root directory. Here is my code for my service-worker.js file:





const myCache = 'static-cache'; const myCache = 'static-cache';

const pageToCache = [ '/offlineApp.html' ]; const pageToCache = [ '/offlineApp.html' ];





self.addEventListener('install', function(event) { self.addEventListener('install', function(event) {

event.waitUntil( event.waitUntil(

caches.open(myCache) caches.open(myCache)

.then(function(cache) { .then(function(cache) {

return cache.addAll(pageToCache); return cache.addAll(pageToCache);

}) })

); );

}); });





self.addEventListener('fetch', function(event) { self.addEventListener('fetch', function(event) {

event.respondWith( event.respondWith(

caches.match(event.request) caches.match(event.request)

.then(function(response) { .then(function(response) {

return response || fetchAndCache(event.request); return response || fetchAndCache(event.request);

}) })

); );

}); });





function fetchAndCache(url) { function fetchAndCache(url) {

return fetch(url) return fetch(url)

.then(function(response) { .then(function(response) {

// check for valid response // check for valid response

if (!response.ok) { if (!response.ok) {

throw Error(response.statusText); throw Error(response.statusText);

}

return caches.open(myCache) return caches.open(myCache)

.then(function(cache) { .then(function(cache) {

cache.put(url, response.clone()); cache.put(url, response.clone());

return response; return response;

}); });

}) })

.catch(function(error) { .catch(function(error) {

console.log('Request failed:', error); console.log('Request failed:', error);

// offline 404 page really needs go here but I have not bothered yet // offline 404 page really needsgo here but I have not bothered yet

}); });

}





Reference service-worker.js and manifest.json in index.html

Our goal, again, is a very limited one. We just want to use PWA to let the user download the app from the page where the app is hosted.





Add the following to the header section of your HTML:





<link rel=”manifest” href=”https://< username>.github.io/manifest.json” /> .github.io/manifest.json” />





: Always use ‘https’ in your links and not ‘http,’ otherwise you will create what is known as a cross-origin error. This is because GitHub resources always use the secure ‘https’ protocol. NOTE





Go to your index.html page and add a section. Add the following code:





if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {

window.addEventListener('load', () => { window.addEventListener('load', () => {

navigator.serviceWorker.register('/service-worker.js') navigator.serviceWorker.register('/service-worker.js')

.then((reg) => { .then((reg) => {

console.log('Service worker registered.', reg); console.log('Service worker registered.', reg);

}); });

}); });

}

Test

That’s pretty much it. If you run your app in your Chrome browser, check out the three vertical dots icon. There should now be an option to install a stand-alone version of your app. Congrats – you’ve got your first PWA up and running!





Troubleshooting

App not working on other browsers?

Not all browsers support the web app manifest the same way Chrome does. But you want your app to work on all browsers if possible. Try updating your meta-tags in index.html to help out other browsers. Add the following to the header section of your index.html file:

<meta name = “apple-mobile-web-app-title” content=”myApp” >

<meta name = “apple-mobile-web-app-status-bar-style” content=”blue” >

<meta name = “apple-mobile-web-app-title” content=”myApp” >

In a typical PWA, there are actually more than just the two icon/icon sizes used. But these two – 192 px and 512 px - are the bare minimum to get a PWA up and running, and this is a bare-minimum tutorial. In fact, I just went out and googled “free test icons,” one for 192 pix and one for 512 px. I copied and pasted them to good ol’ Paint, saved them as jpegs, then uploaded them to a ‘images’ folder in the root directory of the GitHub page.