Webpack plugin for using service workers to precache external dependencies and webpack-generated assets
npx @tessl/cli install tessl/npm-sw-precache-webpack-plugin@1.0.0SW Precache Webpack Plugin is a webpack plugin that generates service worker files using Google's sw-precache library. It automatically creates service workers that precache static assets, handle offline functionality, and manage cache invalidation for webpack-based applications.
npm install --save-dev sw-precache-webpack-pluginconst SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');For ES6+ environments (when webpack supports ES modules in config):
import SWPrecacheWebpackPlugin from 'sw-precache-webpack-plugin';Note: The plugin source uses ES6 imports internally but exports CommonJS for compatibility.
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
module.exports = {
entry: './src/index.js',
plugins: [
// Simplest usage - uses webpack assets automatically
new SWPrecacheWebpackPlugin(),
// With configuration
new SWPrecacheWebpackPlugin({
cacheId: 'my-app-cache',
filename: 'service-worker.js',
minify: true,
staticFileGlobsIgnorePatterns: [/\.map$/]
})
]
};SW Precache Webpack Plugin integrates with webpack's compilation process:
after-emit event to ensure assets are availableCreates a new instance of the webpack plugin for service worker generation.
/**
* SWPrecacheWebpackPlugin - A wrapper for sw-precache to use with webpack
* @constructor
* @param {Object} options - All parameters should be passed as a single options object. All sw-precache options can be passed here in addition to plugin options.
*
* // plugin options:
* @param {string} [options.filename] - Service worker filename, default is 'service-worker.js'
* @param {string} [options.filepath] - Service worker path and name, default is to use webpack.output.path + options.filename
* @param {RegExp[]} [options.staticFileGlobsIgnorePatterns] - Define an optional array of regex patterns to filter out of staticFileGlobs
* @param {boolean} [options.mergeStaticsConfig=false] - Merge provided staticFileGlobs and stripPrefix(Multi) with webpack's config, rather than having those take precedence
* @param {boolean} [options.minify=false] - Minify the generated Service worker file using UglifyJS
* @param {boolean} [options.debug=false] - Output error and warning messages
* @returns {SWPrecacheWebpackPlugin} Plugin instance for webpack
*/
function SWPrecacheWebpackPlugin(options);The plugin uses several default values and constants defined internally.
/**
* Default configuration options applied when no user options are provided
*/
const DEFAULT_OPTIONS = {
cacheId: 'sw-precache-webpack-plugin',
filename: 'service-worker.js',
importScripts: [],
staticFileGlobsIgnorePatterns: [],
mergeStaticsConfig: false,
minify: false,
};
/**
* Default values used internally
*/
const DEFAULT_CACHE_ID = 'sw-precache-webpack-plugin';
const DEFAULT_WORKER_FILENAME = 'service-worker.js';
const DEFAULT_PUBLIC_PATH = '';
const DEFAULT_IMPORT_SCRIPTS = [];
const DEFAULT_IGNORE_PATTERNS = [];interface PluginOptions {
// Plugin-specific options
filename?: string; // Service worker filename (default: 'service-worker.js')
filepath?: string; // Complete service worker path (overrides filename)
staticFileGlobsIgnorePatterns?: RegExp[]; // Patterns to exclude from caching
mergeStaticsConfig?: boolean; // Merge provided globs with webpack config (default: false)
minify?: boolean; // Minify generated service worker (default: false)
// sw-precache options (all supported)
cacheId?: string; // Unique cache identifier (default: 'sw-precache-webpack-plugin')
importScripts?: (string | ImportScriptOptions)[]; // Scripts to import in service worker
staticFileGlobs?: string[]; // File patterns to cache
stripPrefix?: string; // Path prefix to strip from cache entries
stripPrefixMulti?: Record<string, string>; // Multiple prefix replacement rules
replacePrefix?: string; // Prefix replacement for URLs
navigateFallback?: string; // Fallback URL for navigation requests
navigateFallbackWhitelist?: RegExp[]; // Whitelist patterns for fallback
dontCacheBustUrlsMatching?: RegExp; // URLs to skip cache busting
skipWaiting?: boolean; // Skip waiting phase of service worker
clientsClaim?: boolean; // Take control of clients immediately
runtimeCaching?: RuntimeCacheRule[]; // Runtime caching strategies
handleFetch?: boolean; // Enable/disable fetch event handling
maximumFileSizeToCacheInBytes?: number; // Maximum file size to cache
directoryIndex?: string; // Directory index file
ignoreUrlParametersMatching?: RegExp[]; // URL parameters to ignore
verbose?: boolean; // Enable verbose logging
debug?: boolean; // Enable debug warnings
}
interface ImportScriptOptions {
filename?: string; // Script filename (supports [hash] placeholder)
chunkName?: string; // Webpack chunk name (overrides filename)
}
interface RuntimeCacheRule {
urlPattern: string | RegExp; // URL pattern to match
handler: 'cacheFirst' | 'networkFirst' | 'fastest' | 'cacheOnly' | 'networkOnly';
options?: {
cache?: {
name: string; // Cache name
maxEntries?: number; // Maximum cache entries
maxAgeSeconds?: number; // Maximum age in seconds
};
networkTimeoutSeconds?: number; // Network timeout
};
}The plugin exposes internal properties and methods for configuration and webpack integration.
/**
* Returns merged configuration options for sw-precache
* @returns {Object} Combined options from config, user options, and overrides
*/
get workerOptions();
/**
* Main webpack plugin method called by webpack compiler
* @param {Object} compiler - Webpack compiler instance
*/
apply(compiler);
/**
* Configures service worker options based on webpack compilation data
* @param {Object} compiler - Webpack compiler instance
* @param {Object} compilation - Webpack compilation object
* @returns {void}
*/
configure(compiler, compilation);
/**
* Processes importScripts configuration with hash replacement and chunk resolution
* @param {Array} importScripts - Array of script configurations
* @param {string} publicPath - Webpack public path
* @param {Object} compiler - Webpack compiler instance
* @param {Object} compilation - Webpack compilation object
* @returns {void}
*/
configureImportScripts(importScripts, publicPath, compiler, compilation);
/**
* Validates configuration and pushes warnings to webpack compilation
* @param {Object} compilation - Webpack compilation object
* @returns {void}
*/
checkWarnings(compilation);The plugin generates service worker content using the sw-precache library with webpack asset integration.
/**
* Generates service worker content using sw-precache
* @returns {Promise<string>} Generated service worker code
*/
createServiceWorker();
/**
* Writes service worker file to the output file system
* @param {string} serviceWorker - Generated service worker content
* @param {Object} compiler - Webpack compiler instance
* @returns {Promise<void>} Promise resolving when file is written
*/
writeServiceWorker(serviceWorker, compiler);const path = require('path');
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/'
},
plugins: [
new SWPrecacheWebpackPlugin({
cacheId: 'my-project',
filename: 'sw.js',
minify: true
})
]
};const path = require('path');
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name]-[hash].js',
publicPath: 'https://example.com/assets/'
},
plugins: [
new SWPrecacheWebpackPlugin({
cacheId: 'my-project-cache',
filename: 'service-worker.js',
staticFileGlobs: [
'public/images/**/*',
'public/fonts/**/*'
],
stripPrefix: 'public/',
mergeStaticsConfig: true,
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
navigateFallback: '/index.html',
navigateFallbackWhitelist: [/^(?!\/__).*/],
minify: true
})
]
};This generates a service worker at dist/service-worker.js that caches webpack assets plus additional static files.
After the plugin generates the service worker file, you need to register it in your application:
// Register the service worker (client-side code)
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('SW registered:', registration);
})
.catch(registrationError => {
console.log('SW registration failed:', registrationError);
});
});
}new SWPrecacheWebpackPlugin({
cacheId: 'my-app',
runtimeCaching: [
{
urlPattern: /^https:\/\/api\.example\.com\//,
handler: 'networkFirst',
options: {
cache: {
name: 'api-cache',
maxEntries: 50,
maxAgeSeconds: 300
}
}
},
{
urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
handler: 'cacheFirst',
options: {
cache: {
name: 'image-cache',
maxEntries: 100,
maxAgeSeconds: 86400
}
}
}
]
})new SWPrecacheWebpackPlugin({
cacheId: 'my-app',
importScripts: [
{
filename: 'sw-toolbox-[hash].js' // [hash] gets replaced with webpack compilation hash
},
{
chunkName: 'sw-runtime' // Uses webpack chunk by name
}
]
})// Generate separate service workers for different entry points
module.exports = {
entry: {
home: './src/home/index.js',
admin: './src/admin/index.js'
},
plugins: [
new SWPrecacheWebpackPlugin({
cacheId: 'home-cache',
filename: 'home-sw.js',
staticFileGlobs: ['dist/home-*.js', 'dist/home-*.css']
}),
new SWPrecacheWebpackPlugin({
cacheId: 'admin-cache',
filename: 'admin-sw.js',
staticFileGlobs: ['dist/admin-*.js', 'dist/admin-*.css']
})
]
};The plugin provides warning messages for common configuration issues:
// Error and Warning Constants
const CHUNK_NAME_NOT_FOUND_ERROR = 'Could not locate files for chunkName: "%s"';
const CHUNK_NAME_OVERRIDES_FILENAME_WARNING = 'Don\'t use chunkName & filename together; importScripts[<index>].filename overriden by specified chunkName: %j';
const FILEPATH_WARNING = 'sw-prechache-webpack-plugin [filepath]: You are using a custom path for your service worker, this may prevent the service worker from working correctly if it is not available in the same path as your application.';
const FORCEDELETE_WARNING = 'sw-prechache-webpack-plugin [forceDelete]: You are specifying the option forceDelete. This was removed in v0.10. It should not affect your build but should no longer be required.';Common Error Scenarios:
chunkName specified in importScripts doesn't match any webpack chunkfilepath may prevent service worker from working if not in the correct scopeforceDelete option was removed in v0.10 and should no longer be usedchunkName and filename are specified for import scriptsWarnings are displayed when debug: true is set in the configuration options.
compiler.hooks for webpack 4+, compiler.plugin for older versions)