Vue CLI plugin that adds Progressive Web App capabilities including service workers, manifests, and PWA meta tags
—
Service worker generation for production builds using Workbox webpack plugin integration, and development middleware that serves no-op service workers to prevent caching issues during development.
Creates Express middleware that serves a no-op service worker during development to prevent production service worker caching issues.
/**
* Creates development middleware for serving no-op service worker
* @returns {Function} Express middleware function that intercepts /service-worker.js requests
*/
function createNoopServiceWorkerMiddleware(): (req: Request, res: Response, next: NextFunction) => void;Usage Example:
const createNoopServiceWorkerMiddleware = require('@vue/cli-plugin-pwa/lib/noopServiceWorkerMiddleware');
const express = require('express');
const app = express();
app.use(createNoopServiceWorkerMiddleware());
// When accessing /service-worker.js in development, serves the no-op service workerThe actual service worker script served during development that resets any existing service workers.
// Development service worker content
self.addEventListener('install', () => self.skipWaiting());
self.addEventListener('fetch', () => {});
self.addEventListener('activate', () => {
self.clients.matchAll({ type: 'window' }).then(windowClients => {
for (const windowClient of windowClients) {
windowClient.navigate(windowClient.url);
}
});
});In production builds, the plugin integrates with Workbox webpack plugin to generate actual service workers with precaching capabilities.
/**
* Workbox plugin integration for production service worker generation
* Applied automatically when NODE_ENV === 'production'
*/
interface WorkboxIntegration {
/** Plugin mode: 'GenerateSW' (default) or 'InjectManifest' */
workboxPluginMode: 'GenerateSW' | 'InjectManifest';
/** Configuration passed to Workbox webpack plugin */
workboxOptions: WorkboxOptions;
}Two service worker generation strategies provided by Workbox.
/**
* GenerateSW Mode - Automatically generates complete service worker
* Best for: Simple PWAs with standard caching needs
*/
interface GenerateSWMode {
mode: 'GenerateSW';
options: {
/** Cache identifier for service worker */
cacheId?: string;
/** Files to exclude from precaching */
exclude?: RegExp[];
/** Whether to skip waiting during service worker updates */
skipWaiting?: boolean;
/** Whether to claim clients immediately */
clientsClaim?: boolean;
/** Runtime caching strategies */
runtimeCaching?: RuntimeCachingEntry[];
};
}
/**
* InjectManifest Mode - Injects precache manifest into existing service worker
* Best for: Custom service worker logic with precaching
*/
interface InjectManifestMode {
mode: 'InjectManifest';
options: {
/** Path to source service worker file */
swSrc: string;
/** Files to exclude from precaching */
exclude?: RegExp[];
/** Additional Workbox options */
[key: string]: any;
};
}Configuration for caching strategies applied to runtime requests.
interface RuntimeCachingEntry {
/** URL pattern to match for caching */
urlPattern: RegExp | string;
/** Caching strategy handler */
handler: 'CacheFirst' | 'NetworkFirst' | 'NetworkOnly' | 'CacheOnly' | 'StaleWhileRevalidate';
/** Additional caching options */
options?: {
/** Custom cache name */
cacheName?: string;
/** Network timeout for NetworkFirst strategy */
networkTimeoutSeconds?: number;
/** Cache expiration settings */
expiration?: {
maxEntries?: number;
maxAgeSeconds?: number;
};
/** Background sync settings */
backgroundSync?: {
name: string;
options?: any;
};
};
}Usage Examples:
// GenerateSW mode with runtime caching
module.exports = {
pwa: {
workboxPluginMode: 'GenerateSW',
workboxOptions: {
skipWaiting: true,
clientsClaim: true,
runtimeCaching: [
{
urlPattern: /^https:\/\/api\.example\.com\//,
handler: 'NetworkFirst',
options: {
cacheName: 'api-cache',
networkTimeoutSeconds: 3,
expiration: {
maxEntries: 50,
maxAgeSeconds: 300 // 5 minutes
}
}
},
{
urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
handler: 'CacheFirst',
options: {
cacheName: 'images',
expiration: {
maxEntries: 100,
maxAgeSeconds: 86400 // 24 hours
}
}
}
]
}
}
};// InjectManifest mode with custom service worker
module.exports = {
pwa: {
workboxPluginMode: 'InjectManifest',
workboxOptions: {
swSrc: 'src/sw.js',
exclude: [/\.map$/, /manifest$/, /\.htaccess$/]
}
}
};
// src/sw.js - Custom service worker
import { precacheAndRoute, cleanupOutdatedCaches } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';
// Precache and route static assets
precacheAndRoute(self.__WB_MANIFEST);
cleanupOutdatedCaches();
// Custom runtime caching
registerRoute(
({ request }) => request.destination === 'document',
new StaleWhileRevalidate({
cacheName: 'pages-cache'
})
);Files excluded from precaching by default.
const defaultExclusions = [
/\.map$/, // Source maps
/img\/icons\//, // PWA icons (served separately)
/favicon\.ico$/, // Favicon
/^manifest.*\.js?$/ // Manifest files
];The plugin validates Workbox plugin mode against available options.
/**
* Validates workboxPluginMode against available Workbox webpack plugin modes
* @param {string} mode - The specified workbox plugin mode
* @throws {Error} When mode is not supported
*/
if (!(workboxPluginMode in workboxWebpackModule)) {
throw new Error(
`${workboxPluginMode} is not a supported Workbox webpack plugin mode. ` +
`Valid modes are: ${Object.keys(workboxWebpackModule).join(', ')}`
);
}Template for registering service workers in the client application.
// Generated registerServiceWorker.js template
import { register } from 'register-service-worker';
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready() {
console.log('App is being served from cache by a service worker.');
},
registered() {
console.log('Service worker has been registered.');
},
cached() {
console.log('Content has been cached for offline use.');
},
updatefound() {
console.log('New content is downloading.');
},
updated() {
console.log('New content is available; please refresh.');
},
offline() {
console.log('No internet connection found. App is running in offline mode.');
},
error(error) {
console.error('Error during service worker registration:', error);
}
});
}Install with Tessl CLI
npx tessl i tessl/npm-vue--cli-plugin-pwa