This Progressive Web App (PWA) demo showcases the cutting-edge capabilities of web technology by utilizing a robust stack including React, TypeScript, Node.js, PostgreSQL, and styling with Scss/Sass/Less. Designed as both an educational tool and a practical demonstration, it guides users through the intricacies of building a high-performance PWA capable of achieving a perfect Lighthouse score. The project not only highlights best practices for web development and performance optimization but also offers insights into creating seamless, app-like experiences on the web, making it an invaluable resource for developers looking to enhance their skills in crafting modern, efficient web applications.
- View a demo of the project on GitHub Pages Here.
I wanted to demonstrate how to build a PWA that uses a database to store user data locally and syncs with a remote database when online. I also wanted to demonstrate how to use a service worker to cache the app shell and data as well as a manifest file to allow the user to install the app on their device.
To turn your website into a PWA, you'll need the following qualifications:
- HTTPS - Your site must be served over
HTTPS
. This is a requirement for service workers. If you don't have a certificate, you can use Let's Encrypt.
Note
If you're deploying locally, you can still achieve a PWA by using localhost
, but you won't be able to use a service worker or push notifications and it is strongly recommended that you use HTTPS
for a production deployment.
- Service Worker - A Service Worker) is a script that runs in the background and allows you to control how your app handles network requests and cache data. It also allows you to send push notifications to the user (see instructions below for more details).
- Manifest File - A manifest file is a
JSON
file that contains metadata about your app. It allows you to specify the name of your app, the icons that will be used when the app is installed on a device, the background color of the splash screen, and more (see instructions below for more details). - App Shell - The app shell is the minimal
HTML
,CSS
, andJavaScript
required to power the user interface of your app. It is the first thing that is cached by the service worker and is used to provide a fast, reliable, and engaging experience for the user. - Offline Data Storage - A PWA must be able to store data locally on the user's device. This allows the user to continue using the app when they are offline. When the user is online, the data should be synced with a remote database.
- Responsive Design - A PWA must be responsive and work on all devices.
I used the following technologies to build this app:
- React (Frontend)
- TypeScript (JavaScript)
- Node.js (Backend/Server)
- Postgresql (Database)
- Scss/Sass/Less (CSS Preprocessors)
- Workbox Package (Service Worker)
- PWA Asset Generator Package (Manifest File)
- NPM (Package Manager)
- Webpack (Module Bundler)
Note
By default, the application uses client/src/App.scss
to style the application.
The App.sass
and App.css
(compiled from Less) can be used as well, they're interchangable.
Simply uncomment out the line for the CSS Preprocessor you want to use in the client/src/components/UserTable.tsx
file.
- Install Postgresql and create a database named
pwa_db_web_app
.
- Use the
database.sql
file to create the tables and insert the data.
- Change your directory to the project directory and run the following commands:
- Install
npm
if you haven't already:
npm install
- Build the application:
npm run build
- Start the client (frontend):
cd client
npm start
- Start the server (if using a database):
cd server
npm start
- Open your browser and navigate to http://localhost:3000/PWA-Demo-App to view the PWA application.
- Open Lighthouse in Chrome to generate your PWA report.
- I used Workbox to generate the service worker file. To do this, I installed Workbox in the client directory:
npm install workbox-cli --global
- Then generate the service worker file by running:
npx workbox generateSW workbox-config.js
- Use PWA Asset Generator to automatically generate
JSON
for yourmanisfest.json
file as well as theicons
for your logo to make it PWA complicit. - To install PWA Asset Generator run:
npm install -g pwa-asset-generator
- Then create a logo.png file in the root directory of your project. The logo should be at least 512x512 pixels.
Tip
The logo should be square and have a transparent background.
- Then run (Assuming you are in the directory your logo file is in):
npx pwa-asset-generator logo.png icons
The images will be created in the icons directory.
- To send Push Notifications, you'll need to create a VAPID key pair. You can do this by running the following command:
npx web-push generate-vapid-keys
- Then copy the VAPID key pair and paste it into the
server/src/routes/notifications.ts
file. - Then run the following command to start the server:
npm start
- Then open your browser and navigate to http://localhost:3000.
- Then open the Chrome Dev Tools and click on the Application tab.
- Then click on the Service Workers tab -> Push link -> Subscribe button -> Allow button.
- Then copy the Endpoint and paste it into the
server/src/routes/notifications.ts
file. - Then run the following command to send a push notification:
curl -X POST -H "Content-Type: application/json" -d "{\"title\": \"Hello World\", \"body\": \"This is a test notification\"}" http://localhost:3001/notifications
- Then you should see a push notification in your browser.
- Lighthouse is an open-source, automated tool for improving the quality of web pages. You can run it against any web page, public or requiring authentication. It has audits for performance, accessibility, progressive web apps, and more.
- To generate a Lighthouse report, open your browser and navigate to http://localhost:3000.
- Then open the Chrome Dev Tools and click on the Lighthouse tab.
- Click on the Generate Report button.
- I achieved the following perfect scores:
- Performance: 100
- Accessibility: 100
- Best Practices: 100
- SEO: 100
- Progressive Web App: 100
- References to the Lighthouse Report files are located in the docs directory.
Important
Remove the BMC Widget and FontAwesome CSS references in the index.html
file for a perfect Lighthouse Score (see comments in the file on where to remove).
I kept these in for production purposes, but loading third-party cookies and unused CSS libraries slows down the application and is generally not a good practice.
- By default, I'm parsing the table from a Comma-separated values (CSV) file located in the
client/src/data
directory for hosting purposes. You can change this to use Postgresql by modifying theclient/src/App.tsx
file flag tofalse
here:
const useCsv = true;
- To use Less, install the package via npm:
npm install -g less
- Then, change your directory to the
src
folder where theApp.less
file exists and run the following command to generate the.css
file:
lessc App.less App.css
- Be sure to uncomment out the
.css
import in theclient/src/components/UserTable.tsx
file.
- By default, I'm deploying the app to GitHub Pages. You can change this to deploy the app locally without using the repository name
PWA-Demo-App
or to your own GitHub Pages by modifying the following files:
-
/client/package.json
Local:
"homepage": "http://localhost:3000",
GitHub Pages:
"homepage": "https://{your_github_username}.github.io/{your_repository_name}/",
-
/client/src/index.tsx
Local:
navigator.serviceWorker.register('/service-worker.js').then(registration => {
GitHub Pages:
navigator.serviceWorker.register('/{your_repository_name}/service-worker.js').then(registration => {
-
/client/public/index.html
Local:
<link rel="manifest" href="/manifest.json">
GitHub Pages:
<link rel="manifest" href="/{your_repository_name}/manifest.json">
-
/client/public/manifest.json
Local:
"start_url": ".",
GitHub Pages:
"start_url": "/{your_repository_name}/",
-
Then
cd client/public
from the root directory and run the following command to deploy to GitHub Pages:npm run deploy
-
If you're unfamiliar with deploying a static site to GitHub Pages, you can read more about it here: GitHub Pages.
- Progressive Web Apps
- Wikipedia - Progressive Web App
- Single-Page Applications vs Multi-Page Applications: The Battle of the Web Apps
- Single Page Application (SPA) vs Multi Page Application (MPA): Which Is The Best?
- Service Workers
- Workbox
- PWA Asset Generator
- Push Notifications
- Lighthouse
- GitHub Pages
- Let's Encrypt
- Postgresql
- React
- TypeScript
- Node.js
- Scss
- Sass
- Less
- NPM
- Webpack
Happy Coding!
This project is released under the terms of the MIT License, which permits use, modification, and distribution of the code, subject to the conditions outlined in the license.
- The MIT License provides certain freedoms while preserving rights of attribution to the original creators.
- For more details, see the LICENSE file in this repository. in this repository.
Author: Scott Grivner
Email: scott.grivner@gmail.com
Website: scottgrivner.dev
Reference: Main Branch