I’m working on a PWA with Vite and have implemented a service worker (sw.js) to show notifications when the user goes online. The notifications work perfectly in development mode (vite dev), but they don’t work in vite preview (or in a production build).
service worker: sw.js in main directory:
self.addEventListener("install", (event) => {
console.log("Service Worker: Installed");
self.skipWaiting();
});
self.addEventListener("activate", (event) => {
console.log("Service Worker: Activated");
event.waitUntil(self.clients.claim());
});
self.addEventListener("message", async (event) => {
if (event.data === "online") {
console.log("Service Worker: Online");
self.registration.showNotification("You're Online!", {
body: "Sync to the server.",
icon: "/icon.png",
vibrate: [200, 100, 200],
});
}
});
console.log("Service Worker working");
Now in my vite : index.html
<script>
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("/sw.js", { scope: "/" })
.then((registration) => {
console.log("Service Worker registered:", registration);
})
.catch((error) =>
console.error("Service Worker registration failed:", error)
);
});
// Request notification permission on page load
if ("Notification" in window) {
Notification.requestPermission().then((permission) => {
if (permission === "granted") {
console.log("Notification permission granted.");
}
});
}
// Send a message to the SW when online
window.addEventListener("online", () => {
if (navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.postMessage("online");
}
});
}
</script>
Issue in vite preview Mode When I run vite preview, the service worker registers successfully, but the notification does not appear when the user goes online.
But when i run built: index.html using live server it is working fine.
my vite.config.ts
import { VitePWA } from "vite-plugin-pwa";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// /config/
export default defineConfig({
base: "./",
server: {
allowedHosts: true,
},
preview: {
allowedHosts: true,
},
plugins: [
react(),
VitePWA({
registerType: "prompt",
injectRegister: false,
pwaAssets: {
disabled: false,
config: true,
},
manifest: {
name: "AITC App",
short_name: "aitc app",
description: "pwa is the description",
theme_color: "#ffffff",
icons: [
{
src: "/aitc.png",
sizes: "192x192",
type: "image/png",
},
{
src: "/aitc.png",
sizes: "512x512",
type: "image/png",
},
],
},
workbox: {
globPatterns: ["**/*.{js,css,html,svg,png,ico}"],
cleanupOutdatedCaches: true,
clientsClaim: true,
},
devOptions: {
enabled: true,
navigateFallback: "index.html",
suppressWarnings: true,
type: "module",
},
}),
],
});
attaching srcOut for inject also didn't work.