Building a Progressive Web App with React: A Step-by-Step Guide

Progressive Web Apps (PWAs) offer the best of both web and mobile applications. They provide users with a fast, reliable, and engaging experience, even on slow networks or offline. PWAs leverage modern web technologies to deliver app-like experiences directly in the browser. In this step-by-step guide, we’ll walk you through building a PWA with React.

What is a Progressive Web App?

A PWA is a web application that uses modern web capabilities to deliver an app-like experience to users. Key features of a PWA include:

  • Responsive Design: Works on any device with a single codebase.
  • Offline Capabilities: Functions without an internet connection.
  • Push Notifications: Engages users with timely updates.
  • Installable: Can be added to the home screen on mobile devices.

Step-by-Step Guide to Building a PWA with React

Step 1: Setting Up Your React Project

First, you’ll need to create a new React application. Use Create React App to set up the project quickly.

npx create-react-app my-pwa
cd my-pwa

Step 2: Installing Dependencies

To turn your React app into a PWA, you need to install a few dependencies. Create React App includes PWA support out of the box, but you’ll need to tweak some configurations.

Step 3: Configuring the Service Worker

Create React App provides a service worker by default, but it’s disabled. Enable the service worker by modifying src/index.js.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorkerRegistration from './serviceWorkerRegistration';

ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

// Enable service worker
serviceWorkerRegistration.register();

Next, create a serviceWorkerRegistration.js file in the src directory.

// src/serviceWorkerRegistration.js

// This optional code is used to register a service worker.
// register() is not called by default.

const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
window.location.hostname === '[::1]' ||
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);

export function register(config) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
if (publicUrl.origin !== window.location.origin) {
return;
}

window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;

if (isLocalhost) {
checkValidServiceWorker(swUrl, config);

navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://cra.link/PWA'
);
});
} else {
registerValidSW(swUrl, config);
}
});
}
}

function registerValidSW(swUrl, config) {
navigator.serviceWorker
.register(swUrl)
.then((registration) => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
console.log(
'New content is available and will be used when all ' +
'tabs for this page are closed. See https://cra.link/PWA.'
);

if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
console.log('Content is cached for offline use.');

if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
})
.catch((error) => {
console.error('Error during service worker registration:', error);
});
}

function checkValidServiceWorker(swUrl, config) {
fetch(swUrl, {
headers: { 'Service-Worker': 'script' },
})
.then((response) => {
const contentType = response.headers.get('content-type');
if (
response.status === 404 ||
(contentType != null && contentType.indexOf('javascript') === -1)
) {
navigator.serviceWorker.ready.then((registration) => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
registerValidSW(swUrl, config);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}

export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready
.then((registration) => {
registration.unregister();
})
.catch((error) => {
console.error(error.message);
});
}
}

Step 4: Adding a Web App Manifest

A web app manifest provides metadata about your app and allows it to be installed on the user’s device. Create a manifest.json file in the public directory.

// public/manifest.json
{
"short_name": "MyPWA",
"name": "My Progressive Web App",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

Link the manifest in the public/index.html file:

<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />

Step 5: Enabling Offline Capabilities

To enable offline capabilities, your service worker will cache the application shell and serve it from the cache when offline. Configure this behavior in service-worker.js.

// public/service-worker.js
const CACHE_NAME = "my-pwa-cache-v1";
const urlsToCache = ["/", "/index.html", "/offline.html"];

self.addEventListener("install", (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(urlsToCache);
})
);
});

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

self.addEventListener("activate", (event) => {
const cacheWhitelist = [CACHE_NAME];
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (!cacheWhitelist.includes(cacheName)) {
return caches.delete(cacheName);
}
})
);
})
);
});

Step 6: Testing Your PWA

Run your application to ensure everything is working correctly:

npm start

Use Chrome DevTools to test the PWA features. Check the “Application” tab to see the manifest and service worker status. You can also simulate offline mode to test offline capabilities.

Step 7: Deploying Your PWA

Once your PWA is ready, deploy it to a web server. Services like Vercel, Netlify, and GitHub Pages make deployment easy and seamless.

Alternative Option: Ethora Low-Code Web App Engine

If you prefer a low-code solution, consider using the Ethora repository by Dappros. Ethora offers a comprehensive ‘super app’ engine for building PWAs and other applications with minimal coding effort. It includes features such as social sign-in, messaging, digital wallet capabilities, web3 gamification, and more, making it an excellent choice for developers who want to quickly build robust applications.

Conclusion

Building a Progressive Web App with React involves setting up a service worker, configuring a web app manifest, and ensuring your app works offline. By following this step-by-step guide, you can create a PWA that provides a seamless, app-like experience for your users. And if you’re looking for a faster, low-code solution, the Ethora engine is a great alternative to get your project up and running quickly.

Happy coding!

Was this helpful?

0 / 0

Leave a Reply 0

Your email address will not be published. Required fields are marked *