Convert your web application into a Progressive Web App (PWA)

Convert your web application into a Progressive Web App (PWA)

For ReactJS and NextJS

·

5 min read

Prologue

Making a web app is indeed an ingenious skill. It takes a significant amount of effort to build a web application, make it screen-responsive, and add modern features and interactive elements.

Once, you've done everything, the next big thing is to convert your web application into a PWA. Why? PWA gives you access to offline mode, an installable web app, a native mobile application-like experience, and much more.

Introduction

A PWA is a means Progressive Web App. PWAs are web-based apps that provide a mobile app experience, such as fast speed, offline use, and notifications PWAs are designed to work on any platform with a standards-compliant browser.

Features of PWAs

PWAs offer features including:

  1. Push notifications

  2. Caching

  3. Smooth scrolling and animation

  4. Standalone window

  5. App Shell

  6. Accept content from other applications (deep-linking)

  7. Application Offline support

Thus, if you're creating a web application for your mainstream users, it is indeed important to make sure that a PWA is implemented.

Benefits of PWAs

  1. Reliable: They work offline and in low network conditions.

  2. Fast: They load quickly and respond to user interactions smoothly.

  3. Engaging: They provide a rich, app-like experience.

  4. Safe: They are served over HTTPS, ensuring data security.

  5. Discoverable: They can be indexed by search engines.

Making your Web app a PWA

ReactJS

Converting your react application into a PWA requires several steps including:-

  1. Create a React App - To begin you must create a new React project. It can be done via create-react-app, Vite, or any other tool of your choice.

  2. Add a Web App Manifest - A Web App Manifest is a JSON file that provides information about your PWA. It is usually created with a manifest.json file name.

    Consider the following sample manifest file:-

     {
       "theme_color": "#e3405f",
       "background_color": "#dbeafe",
       "display": "standalone",
       "orientation": "any",
       "scope": "/",
       "start_url": "/",
       "name": "Utkarsh Rajput",
       "short_name": "Utkarsh",
       "description": "Full Stack Developer",
       "icons": [
         {
           "src": "/icon-192x192.png",
           "sizes": "192x192",
           "type": "image/png"
         },
         {
           "src": "/icon-256x256.png",
           "sizes": "256x256",
           "type": "image/png"
         },
         {
           "src": "/icon-384x384.png",
           "sizes": "384x384",
           "type": "image/png",
           "purpose": "maskable any"
         },
         {
           "src": "/icon-512x512.png",
           "sizes": "512x512",
           "type": "image/png"
         }
       ]
     }
    
  3. Register a Service Worker - Service workers are JS files that run in the background and enable features like offline functionality and push notifications.

    A service worker file such as service-worker.js must be saved in the public directory.

     // Sample service-worker.jsself.addEventListener('install', function(event) {
       event.waitUntil(
         caches.open('my-static-cache')
           .then(function(cache) {
             return cache.addAll([
               '/',
               '/index.html',
               '/app.js',
               '/styles.css',
             ]);
           })
       );
     });
    
     self.addEventListener('activate', function(event) {
       console.log('Service worker activated');
     });
    
     self.addEventListener('fetch', function(event) {
       event.respondWith(
         caches.match(event.request)
           .then(function(response) {
             return response || fetch(event.request);
           })
       );
     });
    

    Further, this service worker needs to be registered in your app's main file.

     // Installing the service worker from your main file
     if ('serviceWorker' in navigator) {
       navigator.serviceWorker.register('service-worker.js')
         .then(registration => {
           console.log('Service worker registered successfully:', registration);
         })
         .catch(error => {
           console.log('Service worker registration failed:', error);
         });
     }
    
  4. Obtain an SSL certificate - In order to successfully deploy a PWA, an SSL certificate is important as the PWAs can only be served via HTTPS protocol.

  5. Implement Offline Functionality - With the service worker in place, your PWA can now cache assets and work offline. When users visit your PWA, the service worker will cache resources, allowing them to access your app even when they’re not connected to the internet.

  6. Enable Push Notifications - To enable push notifications, you’ll need to use a service like Firebase Cloud Messaging (FCM) or OneSignal. These services provide the infrastructure for sending and receiving push notifications in your PWA.

  7. Deploy and Test - Once you’ve optimized your PWA, it’s time to deploy it to a hosting service. Services like Netlify, Vercel, or GitHub Pages make it easy to host and serve your PWA.

    Also, keep in mind that PWAs can be tricky to test on your local host. Thus, it is recommended that you test your PWA by deploying it to a hosting service provider.

NextJS

Converting your NextJS application into a PWA is more easier than your ReactJS application. Consider the following steps to convert your web app into a PWA-

  1. Add a Web App Manifest - A Web App Manifest is a JSON file that provides information about your PWA. It is usually created with a manifest.json file name.

    Consider the following sample manifest file:-

     {
       "theme_color": "#e3405f",
       "background_color": "#dbeafe",
       "display": "standalone",
       "orientation": "any",
       "scope": "/",
       "start_url": "/",
       "name": "Utkarsh Rajput",
       "short_name": "Utkarsh",
       "description": "Full Stack Developer",
       "icons": [
         {
           "src": "/icon-192x192.png",
           "sizes": "192x192",
           "type": "image/png"
         },
         {
           "src": "/icon-256x256.png",
           "sizes": "256x256",
           "type": "image/png"
         },
         {
           "src": "/icon-384x384.png",
           "sizes": "384x384",
           "type": "image/png",
           "purpose": "maskable any"
         },
         {
           "src": "/icon-512x512.png",
           "sizes": "512x512",
           "type": "image/png"
         }
       ]
     }
    
  2. Add manifest.json in layout.jsx - Go to your root layout.jsx file and add the following code -

     import type { Metadata } from "next";
    
     export const metadata: Metadata = {
       manifest : "/manifest.json",
       //your other metadata
     }
    
  3. Install the NPM package - @ducanh2912/next-pwa. This can be done via the following CLI command -

     npm i @ducanh2912/next-pwa
    
  4. Create a next.config.js file - Add the following code to your next.config.js file.

     const withPWA = require("@ducanh2912/next-pwa").default({
       dest: "public",
       swSrc: "/service-worker.js", // optional, required when using custom service worker
       cacheOnFrontEndNav: true,
       reloadOnOnline: true,
       fallbacks: {
         document: "/offline", // optional
       },
     });
    
     module.exports = withPWA({
       reactStrictMode: false,
       swcMinify: true,
       images: {
         remotePatterns: [
           {
             protocol: "https",
             hostname: "firebasestorage.googleapis.com",
             port: "",
           },
         ],
       },
     });
    
  5. (Optional) Create your custom service-worker.js file - If you want to customize your service-worker, you can create a custom service-worker.js file. You can consider a service worker such as -

     // WARNING: This sample service worker uses Google Workbox
     importScripts(
       "https://storage.googleapis.com/workbox-cdn/releases/6.5.3/workbox-sw.js"
     );
    
     workbox.core.clientsClaim();
     self.skipWaiting();
    
     workbox.precaching.precacheAndRoute(self.__WB_MANIFEST);
    
     workbox.routing.registerRoute(
       ({ request }) => request.destination === "image",
       new workbox.strategies.StaleWhileRevalidate({
         cacheName: "images",
         plugins: [
           new workbox.cacheableResponse.CacheableResponsePlugin({
             statuses: [0, 200],
           }),
           new workbox.expiration.ExpirationPlugin({
             maxEntries: 60,
             maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
           }),
         ],
       })
     );
    
  6. Deploy your PWA - Once you've performed the above steps, you can deploy your PWA using a service such as Vercel. It also takes care of the SSL and other things.

Considerations

You can use a tool such as Lighthouse to audit your PWA and make sure it meets the PWA. It gives you all the required insights and warnings if something is off and preventing your web application from becoming a PWA.

Did you find this article valuable?

Support Utkarsh by becoming a sponsor. Any amount is appreciated!