PWAs are more or less regular websites written using HTML, CSS, and JavaScript. In this article, I will show you how to create a simple PWA using Reactjs in typescript. In the previous article, I introduce about PWA. You can find the previous from here.
PWA checklist
- runs over HTTPS
- has a manifest.json
- has a serviceworker (javascript .. between web app and network for notifications)
- Responsive, smooth and app like
- Offline working by caching core assets(html, css, js, logos etc)
- Is installable
PWAs are more or less regular websites written using HTML, CSS, and JavaScript. In this article, I will show you how to create a simple PWA using Reactjs in typescript. In the previous article, I introduce about PWA. You can find the previous from here.
PWA checklist
- runs over HTTPS
- has a manifest.json
- has a serviceworker (javascript .. between web app and network for notifications)
- Responsive, smooth and app like
- Offline working by caching core assets(html, css, js, logos etc)
- Is installable
Getting started
In this document, I assume that you completed to setup your local development environment. If you didn’t, here are some useful links to setup your local environment. You will need to have
You can create a React PWA app using the following PWA custom template CLI in typescript.
npx create-react-app my-app-name --template cra-template-pwa-typescript
When you create a react application using create-react-app cli, you don’t have to worry about babel and web-pack setup. Because all of them come together.
Let’s run your web application
cd my-app
yarn start (npm start)
It will start your web server in any browsers automatically.
Folder structure
index.tsx
This is the application start point. React Dom is rendered here.
package.json
contains declaration of dependencies of the application.
yarn.lock
contains version lists of application dependencies to prevent install newer versions randomly when running yarn or npm command.
node_modules/
contains actual application dependencies.
service-worker.ts
a JavaScript script that runs in the background, independently from the website itself and make features possible that only in native apps can. Such as background sync, push notifications, offline experiences.
manifest.json
includes the name of the PWA, its icon, description etc
Audit PWA using Lighthouse tool
Let’s check whether PWA we have just created meet the PWA’s checklists. To do that we use Lighthouse.
Lighthouse is a Chrome dev tool to improve web pages quality.
- In Google Chrome, open PWA web server
- Open Chrome DevTools and open Lighthouse tab.
- Select Progressive web app and mobile or desktop
- Click “Generate Report”
Let’s solve those issues one by one.
1. Web app manifest or service worker do not meet the installability requirements.
Even if service-worker.tsx file is already created, you need to register a service-worker into the index.tsx file. Change the following line into serviceWorkerRegistration.register();
Configure a manifest.json file
- Register app name in manifest.json
- Save a favicon in the public folder.
An .ico file is just a file that browsers recognize is an icon, and the file contains multiple sizes and colors depths that the computer can scale accordingly.
- Save 192x192 and 512x512 sized logos in he public folder.
Logo generator: https://cthedot.de/icongen/ , https://realfavicongenerator.net, https://maskable.app/editor
- Save a maskable icon
On Android, maskable icon lets developers get rid of the default white background around their icons and use the entire provided space by generating adaptive icons.
In the PWA, you need to configure a maskable icon by yourself.
- Create your own maskable icon
- You can create a maskable icon from your logo png file using this tool.
- Register maskable icon into the manifest.json file.
- Icons used in places like the home screen, app launcher, splash screen etc are declared in the manifest.json file. If you create a react app using create-react-app cli, manifest.json file will be created automatically. You can register your maskable icon In the manifest.json file’s icons field. Maskable icon should have purpose field with ‘maskable’ value.
- This is how sample manifest.json file looks like.
{
... "icons": [
... {
"src": "images/maskable_icon_x192.png",
"type": "image/png",
"sizes": "192x192",
"purpose": "maskable" // <-- New property value `"maskable"`. },
... ],
... }
Does not register a service worker
- Copy paste the following code in to the service-
const CACHE_NAME = "cache_sample";
const urlsToCache = ["index.html", "offline.html"];
const version = "v0.0.1";//install sw at first time
//place to cache assets to speed up the loading time of web page
self.addEventListener("install", (event: any) => {
console.log("sw install event");
event.waitUntil(
caches.open(version + CACHE_NAME).then((cache) => {
console.log("opened cache");
return cache.addAll(urlsToCache);
})
);
});//Activate the sw after install
//Place where old caches are cleared
self.addEventListener("activate", (event: any) => {
console.log("sw activate event");
event.waitUntil(
caches.keys().then((cacheNames) =>
Promise.all(
cacheNames
.filter((cacheName) => {
return cacheName.indexOf(version) !== 0;
})
.map(function (cachName) {
return caches.delete(cachName);
})
)
)
);
});//listen for requests
self.addEventListener("fetch", (event: any) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
Let’s explain above code. Service worker events are handled in this section. You can read further about service worker events from here.
- Install event only occurs when service worker is newly registered or updated. This is the right place where precaching assets. Above code, we cached index.html and offline.html files.
- Activate event is triggered when service worker is activated after service worker installation is completed. In the activate events, you can clear old caches.
- Fetch event is triggered when network request is called. You can check whether response is cached previously in the install event.
- Create offline.html file in the public/ folder
This file will be rendered when network status is offline as declared in the service-worker.ts file. You could copy and paste the following content into the offline.html file temporarily. Then you can edit this file how you want.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PWA sample</title>
</head>
<body>
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Please go ONLINE
</p>
</header>
</div>
</body>
</html>ƒ
Deploy PWA to AWS amplify
There are various ways to deploy PWA to production. But I found one of the easiest way is to use AWS amplify because it helps reactjs app to web with following features such as continuous workflow, monitoring, real time deploying, easy to set a domain.
PWA should run on HTTPS. Let’s deploy your PWA to the AWS server. In this document we will use AWS amplify service to deploy our PWA.
- Push your project into the version control server. I pushed my source code to the github server. AWS amplify can connect other source control servers such as Bitbucket, Gitlab etc.
- You can find the whole source code from here.
- Configure your deployment in the amplify console
- New app⇒ Host web app
- Connect your Github repository to AWS amplify.
- Configure repository and branch of your source code.
- Done!! AWS amplify service makes CI/CD easy. After connecting your PWA’s github repository to AWS amplify, your changes is automatically deployed after every push to your selected branch like the following
How to install
For android
For ios, safari support “Add to Home Screen.” feature. To install pwa you can tap the ‘Share’ button, scroll down and tap ‘Add to Home Screen.’ Enter the name for the app then tap add. The PWA will show up on your home screen.
Let’s audit your PWA once more.
Finally you can audit your PWA using Google’s audit tool named Lighthouse tool.