[000Webhost] Working With PWA Optimization Using React JS/Typescript

Information Last Tested Valid: 09 August 2023

Some Environment Information

Programming Platform: React Typescript

Code Editor: Visual Studio Code

CSS: Standard CSS + TailwindCSS

Assistant: ChatGPT 3.5 (Free Plan)

App Information

At first, this was just to get used to React Typescript after a while of not touching it, but decided to see whether I can make it PWA Compliant. Mostly utilized Tailwind CSS to produce responsiveness. I'm mostly a beginner so based on the sources I've read online, to truly test whether an app is PWA, it must be served on an HTTPS, and the only way I can do that without incurring costs is to build my app and transfer it over to 000webhost. 

The App itself is a full-stack app (not sure whether I'm using that term right, well, you'll get it as I explain further), as in it has both a front-end folder using React and a back-end folder using Node.js. 

Limitations

000Webhost's Free Plan does not appear to be able to start up the server (back-end) of my app, but at least I was able to get the front-end up and running in some way for me to do my tests.

Guide

I will be running through my codes and explain as needed.

Every PWA needs a manifest.json, and so I filled in accordingly, this manifest.json should be in your /public folder of your front-end directory (i.e. React):

{
  "short_name": "Display",
  "name": "Display Information",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "48x48",
      "type": "image/x-icon"
    },
    {
      "src": "favicon-16x16.png",
      "sizes": "16x16",
      "type": "image/x-icon"
    },
    {
      "src": "favicon-32x32.png",
      "sizes": "32x32",
      "type": "image/x-icon"
    },
    {
      "src": "logo192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "logo512.png",
      "type": "image/png",
      "sizes": "512x512"
    },
    {
      "src": "maskable-icon.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable any"
    }
  ],
  "start_url": "/",
  "scope": "/",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}

I just filled as such for my manifest.json.Additionally, I had to find a specific icon, and then generate a favicon.ico file and the other PNGs as well.

Next, is configuring the service worker, you can find a better explanation on what this does online, but basically what I understand is it helps to cache your files, making your site "accessible" despite being in offline state. Having the code being able to successfully register a service worker, would also make the "Add [App Name] To Homescreen" Prompt appear when user loads the page in their mobile. The service-worker.js should be located at the same place as your manifest.json, meaning in the /public folder.

My service-worker.js code:

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

self.__WB_MANIFEST = [
  { url: '/index.html', revision: '000001' },
  { url: '/static/js/main.2d8110b7.js', revision: '000002' },
  { url: '/static/js/787.c0f59c1e.chunk.js', revision: '000003' },
  { url: '/static/css/main.0c818be7.css', revision: '000004' },
  { url: '/favicon.ico', revision: '000006' },
  { url: '/favicon-16x16.png', revision: '000007' },
  { url: '/favicon-32x32.png', revision: '000008' },
  { url: '/logo192.png', revision: '000009' },
  { url: '/logo512.png', revision: '000010' },
  { url: '/maskable_icon.png', revision: '000011' },
];

workbox.precaching.precacheAndRoute(self.__WB_MANIFEST);

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

The self.__WB_MANIFEST = [ ...] should include all the files that you want to cache (at least I believe that's what it does). 

And then in addition to the above, you should add the following lines of code to your root file which in my case would be index.tsx and it could be index.js or index.jsx depending on your environment:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js')
    .then(registration => {
      console.log('Service Worker registered with scope:', registration.scope);
    })
    .catch(error => {
      console.error('Service Worker registration failed:', error);
    });
}

Add it right after all the import statements.

With that, execute "npm run build" locally and it will create a build folder. When that's done, in your 000webhost, you may remove all files from the public_html folder at the File Manager. Copy all the files in your app's /build folder into the /public_html. Save and close, and access your site.

With that, you should be able to test your React App's PWA Compliant with Google Developers Lighthouse or directly access the site in mobile phone and it should trigger the "Add [App Name] to Homescreen" which clearly tells (imo) that the application is PWA if you followed all my steps.

If by any chance, it did not work, or any errors occured, please write down in the comments, as there's a chance I may have missed out on some steps.

Final Words

As someone who enjoys testing freely without paying, and someone who would go through great lengths to find my answer, this was it for a very specific problem that I had recently. 

I did not have any thoughts of posting a blog post until today, but I felt as someone who have lurked through the internet all the time, especially with how long I took to finally get a working solution for myself, maybe it would be helpful for future lurkers if I share what worked for me (if anyone else even gets to read this), and it would be great for me to compile all my current and future resolved problems for review when needed. 

Comments