Introduction
Progressive Web Apps (PWAs) combine the best of web and mobile apps. With React and Vite, you can build a blazing-fast app and convert it into a PWA using vite-plugin-pwa
. In this guide, we’ll cover how to configure PWA support in a React project.
Why Use Vite Plugin PWA?
The vite-plugin-pwa
plugin simplifies PWA setup. It handles service workers, offline caching, and web app manifests automatically. Instead of writing a complex service worker manually, you just add configurations in vite.config.js
.
⚠️ Note: Without PWA setup, your React app won’t support offline usage, push-like features, or install prompts.
Also, all assets (icons, offline.html
, screenshots, favicon) must exist in your public/
folder — otherwise the manifest and service worker will not function correctly.
Installing Dependencies
First, install vite-plugin-pwa
along with React and TailwindCSS (if needed).
npm install vite-plugin-pwa --save-dev
Configuring vite.config.js
Update vite.config.js
to register VitePWA
plugin. Below is a sample configuration:
import path from "path";
import { fileURLToPath } from "url";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import { VitePWA } from "vite-plugin-pwa";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default defineConfig({
plugins: [
react(),
VitePWA({
registerType: "autoUpdate",
includeAssets: [
"favicon.ico",
"apple-touch-icon.png",
"pwa-192x192.png",
"pwa-512x512.png",
],
manifest: {
name: "Quran App",
short_name: "Quran",
start_url: "/",
display: "standalone",
background_color: "#ffffff",
theme_color: "#16a34a",
icons: [
{
src: "pwa-144x144.png",
sizes: "144x144",
type: "image/png",
},
{
src: "pwa-192x192.png",
sizes: "192x192",
type: "image/png",
},
{
src: "pwa-512x512.png",
sizes: "512x512",
type: "image/png",
},
{
src: "pwa-512x512.png",
sizes: "512x512",
type: "image/png",
purpose: "any maskable",
},
],
screenshots: [
{
src: "screenshot-desktop.png",
sizes: "1280x720",
type: "image/png",
form_factor: "wide",
},
{
src: "screenshot-mobile.png",
sizes: "540x720",
type: "image/png",
form_factor: "narrow",
},
],
},
workbox: {
navigateFallback: "/offline.html",
globPatterns: [
"**/*.{js,css,html,ico,png,svg}",
],
runtimeCaching: [
{
urlPattern: ({ url }) => url.pathname.startsWith("/data/"), // 👈 any /data/** file
handler: "CacheFirst",
options: {
cacheName: "quran-json",
expiration: {
maxEntries: 200, // adjust based on how many files
maxAgeSeconds: 60 * 60 * 24 * 365, // 1 year
},
},
},
],
},
}),
],
resolve: {
alias: {
"~": path.resolve(__dirname, "./src"),
},
},
server: {
host: "localhost",
port: 4000,
},
});
Registering the Service Worker
To activate the PWA, register the service worker in your entry file (main.jsx
or index.jsx
).
import { registerSW } from 'virtual:pwa-register'
const updateSW = registerSW({
onNeedRefresh() {},
onOfflineReady() {},
});
Testing the PWA
Run your app, then open Chrome DevTools → Application → Manifest. You should see your icons, theme color, and install option. Try turning off your internet to check if offline caching works.