Use Workbox
Use Workbox when handwritten service worker code is becoming a cache invalidation project.
Choose A Mode
| Mode | Use when | Trade-off |
|---|---|---|
generateSW | You need precaching and straightforward runtime caching | Less custom service worker control |
injectManifest | You need custom push, sync, routing, or complex offline behavior | More code and lifecycle responsibility |
Vite PWA Shape
import { defineConfig } from 'vite';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({
plugins: [
VitePWA({
registerType: 'prompt',
strategies: 'generateSW',
manifest: {
name: 'Ledger',
short_name: 'Ledger',
start_url: '/',
scope: '/',
display: 'standalone',
theme_color: '#0f172a',
background_color: '#ffffff',
icons: [
{ src: '/icons/icon-192.png', sizes: '192x192', type: 'image/png' },
{ src: '/icons/icon-512.png', sizes: '512x512', type: 'image/png' },
{ src: '/icons/icon-maskable.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' },
],
},
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
runtimeCaching: [
{
urlPattern: /^https:\/\/api\.example\.com\/reference\//,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'reference-data',
expiration: { maxEntries: 50, maxAgeSeconds: 60 * 60 * 24 },
},
},
],
},
}),
],
});
Use injectManifest When
- You need custom notification click routing.
- You need explicit offline mutation replay.
- You need custom cache migration.
- You need to coordinate service worker updates with app UI.
Gotcha: Workbox reduces boilerplate. It does not remove the need to define freshness, privacy, cache size, and update rules.