Progressive Web Apps (PWAs) have rapidly grown in popularity as essentially fast, performance-based web applications streamlined for delivering mobile app-like experiences. Progressive Web Apps are built using front-end technologies like HTML, CSS, and JavaScript to create a level of usability and performance that’s in parity with native mobile applications. They are responsive, consume lesser data and storage space, and supports push notifications and offline usage in the browser.
Building a progressive web app has now become a web development trend every enterprise wants to follow. Big players such as Twitter and Flipboard recently launched their progressive web apps to deliver mobile experiences to users, without requiring them to install the app. In this article, you will learn how to build a progressive web app using React. So, let’s get started.
Setting Up a Progressive Web App in React
- To start, let’s generate a basic React application with create-react-app.
- To do so, switch to the directory in which you want to save your app, and run the following.
npm install -g create-react-app
create-react-app pwa-app
Now install React Router.
cd pwa-app
npm install --save [email protected]
You need to replace the “src/App.js” content using the below code to get a basic template with navigation.
import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
Now, you will have to update the default styles by replacing your “src/App.css” with the below styles to make your app look clean.
.App {
text-align: center;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 40vmin;
pointer-events: none;
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
Now Run npm start to test our your app. Not much to look at, but it’ll serve our purposes just fine. Let’s get started converting this into a PWA.
npm start
Installing Lighthouse and Audit
- Lighthouse is an automated, open source tool for testing applications against the PWA checklist. It facilitates audits for accessibility, performance, and more.
- Test your app with Lighthouse. Click the Lighthouse icon from the top right corner in Chrome and then click on the ‘Generate Report’ button.
Registering a Service Worker
Service workers are the proxy servers that connect the app and network. With Service Worker, you will have to intercept network requests and save cached files. This will enable your app to work even when the network is unavailable.
Also Read:- How to Make Real Time Notification System Using Socket.io and Node.JS
Create a blank Worker.js file in your app’s public folder and add the following code to that file.
// Flag for enabling cache in production
var doCache = true;
var CACHE_NAME = 'pwa-app-cache';
// Delete old caches
self.addEventListener('activate', event => {
const currentCachelist = [CACHE_NAME];
event.waitUntil(
caches.keys()
.then(keyList =>
Promise.all(keyList.map(key => {
if (!currentCachelist.includes(key)) {
return caches.delete(key);
}
}))
)
);
});
// This triggers when user starts the app
self.addEventListener('install', function(event) {
if (doCache) {
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
fetch('asset-manifest.json')
.then(response => {
response.json();
})
.then(assets => {
// We will cache initial page and the main.js
// We could also cache assets like CSS and images
const urlsToCache = [
'/',
assets['main.js']
];
cache.addAll(urlsToCache);
})
})
);
}
});
// Here we intercept request and serve up the matching files
self.addEventListener('fetch', function(event) {
if (doCache) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
}
});
Now check if the browsers support the service workers and thereafter register worker.js.
To do this, you need to add the following script to public/index.html file (note that shrink-to-fit=no from the viewport meta tag has been removed).
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('worker.js').then(function(registration) {
console.log('Worker registration successful', registration.scope);
}, function(err) {
console.log('Worker registration failed', err);
}).catch(function(err) {
console.log(err);
});
});
} else {
console.log('Service Worker is not supported by browser.');
}
</script>
You must restart your progressive web app and reload the browser after which you will notice the “Worker Registration Successful” message in the developer console. Now regenerate the Lighthouse report.
Improving Progressive Nature of the App
Your progressive web app will render an empty root div until the JavaScript loads and React hooks the initial route. You must ensure your app works without any JS loading and displays a bit of CSS and HTML before React comes into play. Your updated index.html will look like this.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!-- Tell the browser it's a PWA -->
<meta name="mobile-web-app-capable" content="yes">
<!-- Tell iOS it's a PWA -->
<meta name="apple-mobile-web-app-capable" content="yes">
<title>React App</title>
<style type="text/css">
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
.navbar {
background-color: #01C8E5;
text-align: center;
}
.navbar a {
display: inline-block;
padding: 10px;
color: #fff;
text-decoration: none;
}
.page-info {
text-align: center;
font-weight: bold;
}
</style>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root">
<div class="navbar">
<a href="/">Feed</a>
</div>
<p class="page-info">
Loading an awesome app...
</p>
</div>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('worker.js').then(function(registration) {
console.log('Worker registration successful', registration.scope);
}, function(err) {
console.log('Worker registration failed', err);
}).catch(function(err) {
console.log(err);
});
});
} else {
console.log('Service Worker is not supported by browser.');
}
</script>
</body>
</html>
Now use Lighthouse to re-audit your progressive web app and you will notice an improvement in the app's performance.
Adding Splash Icons
You’re required to add a 512x512 icon to show up on the splash screen. To do so, you will have to update the manifest.json and add the icon t0 the public folder.
Also, use the following meta tags to allow the browser to identify that your progressive web app is a PWA.
<!-- Tell the browser it's a PWA -->
<meta name="mobile-web-app-capable" content="yes">
<!-- Tell iOS it's a PWA -->
<meta name="apple-mobile-web-app-capable" content="yes">
Finally, you’ve created your first progressive web app with React.js!
Here You Can view Source Code: GitHub