Progressive Web Applications (PWAs) combine the best features of websites and native applications to deliver a fast, reliable, and engaging user experience.
A Progressive Web Application (PWA) is a type of web app that delivers a native app-like experience. PWAs offer several benefits:
Express.js can serve as the backend to deliver resources and data, while the frontend code in JavaScript enables PWA capabilities. This chapter will guide you through integrating PWA features with Express.js.
To get started, create a basic Express project to serve as the backend for your PWA.
mkdir express-pwa
cd express-pwa
npm init -y
npm install express
Create server.js
and configure it as follows
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Organize the project with a public
folder for static files, where index.html
, JavaScript, CSS, and service worker files will reside
express-pwa/
├── public/
│ ├── index.html
│ ├── sw.js
│ └── manifest.json
└── server.js
To transform this Express.js application into a PWA, let’s add essential PWA components like the service worker, caching strategies, offline support, a web app manifest, and push notifications.
A service worker is a JavaScript file that runs in the background, intercepting network requests, caching responses, and managing offline behavior.
sw.js
)
const CACHE_NAME = 'pwa-cache-v1';
const urlsToCache = [
'/',
'/index.html',
'/styles.css',
'/script.js'
];
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);
})
);
});
urlsToCache
upon installation.index.html
In the <head>
or <body>
section of your index.html
, add:
Caching is vital for reducing load times and providing content offline. In addition to static files, consider caching API responses.
Example of Network-First Strategy:
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request).catch(() => caches.match(event.request))
);
});
By caching assets and responses, users can access your PWA even without an internet connection.
For dynamic content like API calls, implement a fallback cache
self.addEventListener('fetch', event => {
if (event.request.url.includes('/api/')) {
event.respondWith(
caches.open('api-cache').then(cache =>
fetch(event.request)
.then(response => {
cache.put(event.request, response.clone());
return response;
})
.catch(() => caches.match(event.request))
)
);
}
});
The manifest file configures the PWA’s metadata, like icons, theme colors, and display modes.
manifest.json
{
"name": "Express PWA",
"short_name": "PWA",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"description": "A sample Progressive Web App using Express.js",
"icons": [
{
"src": "/icons/icon-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/icons/icon-512x512.png",
"type": "image/png",
"sizes": "512x512"
}
]
}
Add the manifest link to index.html:
Push notifications engage users by delivering messages even when the PWA is not active.
Integrating PWA features with Express.js is an effective way to enhance user experience by enabling offline access, push notifications, and faster load times. With features like service workers, caching strategies, and a web app manifest, PWAs create a seamless experience across devices. Happy Coding!❤️