Creating a simple PWA

PWA (aka Progressive Web Apps) is a type of application software delivered through the web, built using common web technologies including HTML, CSS and JavaScript. It is intended to work on any platform that uses a standards-compliant browser.

PWA is something that once you learn, you should be able to implement to almost any of your projects because the code is same for each PWA, no matter what the application does. I’ll be able to give you a template that you can add to your website, and thus, create a PWA.

PWA allows you to “install” your websites to your computer and mobile devices, which can be then used even offline and works like a normal app.

A PWA contains 4 essential things:

  1. manifest.json: it is more like the config file of the PWA
  2. sw.js: PWAs use Service Workers to cache assets and make them progressive
  3. some JS code to register the service workers
  4. a file full of logos of your website each one of a different dimension for each device.

We’ll create a manifest.json first.

  1. Go to https://app-manifest.firebaseapp.com/ and fill in all the details of your app. Make sure to leave ‘Orientation’, ‘Start URL’ and ‘Application Scope’ as it is. As for the display mode, I recommend you choose ‘Standalone’ as that is what makes the PWA a PWA :wink: but you’re free to choose whatever you like. Fill in background color and theme color according to your wish. Click on “Copy” near the manifest.json preview.

  2. Create a new file named manifest.json and paste all the contents into that file.

  3. First things first, you should have a 512x512 sized logo for the PWA. Go to https://app-manifest.firebaseapp.com/ and then fill in all the details. Make sure to leave ‘Orientation’, ‘Start URL’ and ‘Application Scope’ as it is. As for the display mode, I recommend you choose ‘Standalone’ as that is what makes the PWA a PWA :wink: but you’re free to choose whatever you like. Then on the right side, upload the 512x512 icon and you’ll get to download a ZIP file which contains your logo with different dimensions along with the manifest.json file with all the values we entered. For your PWA, you need an icon, with a recommended size of 512x512 pixels. Then, you can use a module named pwa-asset-generator to generate assets for your PWA.

$ npm install --global pwa-asset-generator
pwa-asset-generator /path/to/icon/png/jpg ./pwaicons/ -m ./manifest.json -i path/to/index.html

All the icons and splash screens will be generated in the pwaicons/ folder.

It will also automatically update your index.html file with the necessary meta tags.

You can configure the CLI to modify the generated icons and related config, see https://github.com/onderceylan/pwa-asset-generator#usage

If you change the location of the logos, make sure to update their paths in manifest.json as well, because the manifest.json has each of the logos (of different sizes) with their urls.

  1. Now for some JS! Create a file named sw.js or anything that indicates that the file is a service worker.

Copy this code into your sw.js file:

const staticCacheName = 'name-of-pwa';
const assets = [
  './scripts.js',
  './style.css',
];

self.addEventListener('install', evt => {
  evt.waitUntil(
    caches.open(staticCacheName).then((cache) => {
      console.log('caching shell assets');
      cache.addAll(assets);
    })
  );
});

self.addEventListener('activate', evt => {
  evt.waitUntil(
    caches.keys().then(keys => {
      return Promise.all(keys
        .filter(key => key !== staticCacheName)
        .map(key => caches.delete(key))
      );
    })
  );
});

self.addEventListener('fetch', evt => {
  evt.respondWith(
    caches.match(evt.request).then(cacheRes => {
      return cacheRes || fetch(evt.request);
    })
  );
});

In line 2 of the code, you’ll see an array named assets. And I have included a few urls as an example. In that array, make sure to add all the assets your project uses, such as images, fonts, scripts and styles. What happens is, the service worker will cache all the urls and files listed in the array for a “Progressive Web App”. Also make sure to replace name-of-pwa on line 1 with the name of your pwa (or any name for identification of the cache).

  1. Now, we move towards the HTML file. In your main HTML file, before the closing <head> tags, add the following code:
<script>
if('serviceWorker' in navigator){
  navigator.serviceWorker.register('sw.js')
    .then(reg => console.log('service worker registered'))
    .catch(err => console.log('service worker not registered', err));
}
</script>

In line 2 of the above code, make sure to replace sw.js with the file path of the service worker file we created in the above step.

  1. Then in our HTML file, we also add a link to the manifest.json file. Add the following code before the closing <head> tags:
<link rel="manifest" href="/manifest.json">

Make sure the href points towards the location of the manifest.json file.

All the above files including the images of different sizes are static assets, so if you have a separate configuration for static assets (like the public folder for an Express/Node.js setup), make sure to add all the above files into the static directory and make sure the urls everywhere point correctly to the desired file.

To make sure your PWA works fine,

  1. You should see a log in your DevTools console saying “service worker registered”

  2. On Chrome, you should see an Install button on the right side of the address bar.

  3. It should work offline (after visiting the app once online)

  4. Audits for Progressive Web Apps on Lighthouse should give a good score and determine whether it’s a PWA based on certain aspects of PWAs, with which you can improve your PWA.

Some great PWAs to check out:

  • Hoppscotch
  • MarkMe!
  • Twitter - yes, Twitter is a really great PWA. There’s almost no difference in installing Twitter’s website as a PWA and installing the Twitter app from the Play Store or iOS Store.

~Bonus~:

You can upload your PWA to Google Play Store which can then be installed. (Instructions for that coming up soon!)

8 Likes

before the word gets around we can pretend we hacked school ipads and installed the twitter app on them
these are all quite great apps, hhopscotch’s ui looks a bit like discord on the side.
You know what should be a PWA if it isn’t already: Scratch! I actually forked scratch-3 in it’s early developement just to sort of turn it into a PWA

2 Likes

Actually Hoppscotch is Postwoman.io’s new name.

Postwoman (now Hoppscotch) is an online alternative to Postman

1 Like

There’d be a lot of assets to cache, including all the sprites and backdrops to create an effective PWA for Scratch.

Are you talking about scratch.mit.edu or what?

I often use that but did not notice the change.

1 Like

Yes, https://scratch.mit.edu

I see.

Is a favicon really necessary?

Yes, it’s required for a PWA. And one icon is not enough, you need to generate the icon for different sizes (for various devices). I know, this can be a bit time consuming and exhausting (especially on Glitch because you can’t simply just upload those icons to Assets :sweat_smile:).

2 Likes

I see. Thank you.

2 Likes

When I clicked the Generate .ZIP button, I got this error-

Go 1.9 is no longer available. Please refer to Feature deprecations  |  Google App Engine standard environment docs  |  Google Cloud for more information.

That is really weird, that was a really good tool, let me see if there are any alternatives to that generator, although it worked last week.

I have found a workaround, will be updating the main post soon.

@R4356th I have update the main post, it should work now.

2 Likes

I know something that does something similar but it doesn’t look as good

And what would that be?

I found this but it seems to be more icon oriented
https://www.favicon-generator.org/

That would be great as well, we can still use the Web App Manifest Generator that I originally posted to generate manifest files.

this is off topic but MarkMe! is not a very good PWA

(no offense, lol, I was just joking with @khalby786)

Great tutorial anyways!