SWPrecacheWebpackPlugin is a webpack plugin for using service workers to cache your external project dependencies. It will generate a service worker file using sw-precache and add it to your build directory.
This Webpack plugin generates a service worker using sw-precache that will cache webpack's bundles' emitted assets. You can optionally pass sw-precache configuration options to webpack through this plugin.
This article assume you have basic knowledge of PWA and Webpack.
NOTE: It is recommended to read about basic PWA setup to know about PWA requirements, Web App Manifest, Service Worker and Lighthouse.
Install & Configure SWPrecacheWebpackPlugin
Install sw-precache-webpack-plugin
.
npm install --save-dev sw-precache-webpack-plugin
Edit your webpack configuraion file.
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin')module.exports = { ... plugins: [ ... // service worker caching new SWPrecacheWebpackPlugin({ cacheId: 'myapp', filename: 'service-worker.js', staticFileGlobs: ['dist/**/*.{js,css}', '/'], minify: true, stripPrefix: 'dist/', dontCacheBustUrlsMatching: /\.\w{6}\./ }) ], ...}
I am using vue-webpack-boilerplate, so the service worker will be generated at dist/service-worker.js
. Looking inside this file you shall see the assets which will be cached by service worker.
...var precacheConfig = [ ["service-worker.js","d3713395f64534beb43d3a80883762d3"], ["static/css/app.css","eb9f16dfeabee33d2974c202d1740c9b"], ["static/css/vendor.css","da2c94e8757b06335e628b0030e00591"], ["static/js/app.js","626cf27bbc683df3db780650b1f6c00f"], ["static/js/manifest.js","81bb8bd7f534ad7862c3b8a0fd2ded9e"], ["static/js/sw.js","fe5fe7029d8b78fe22649e55c8a931c3"], ["static/js/vendor.js","db2ab78ce43156b92a611c7dc478fb27"]];...
NOTE: if the path generated (static/
for my case) is incorrect, you can use stripPrefixMulti to do a find & replace
operation.
new SWPrecacheWebpackPlugin({ ... stripPrefixMulti: { 'dist/static/': '/static/pack/', 'dist/': '' },})
NOTE: if you want to cache urls which is not part of this webpack (e.g /
, /about
, /data.json
, etc.), you can use dynamicUrlToDependencies
new SWPrecacheWebpackPlugin({ ... // specify external url to cache: whenever the url content changed/updated, change v1 to another value to indicate changes // other mechanism is available as well, read the docs dynamicUrlToDependencies: { '/': 'v1' },})
NOTE: if you want the service worker to include other features (e.g. push notification) besides caching, you can add extra script logic using importSripts. In this case, two javascripts shall be fetched for service worker. You can also use templateFilePath to modify sw-precache template file to include your logic, but this method is more complicated. You can look into this and this as well.
importScripts: [ // assume this js file is written manually outside of webpack { filename: '/static/js/sw-push-notification.js' }})
or
module.exports = { entry: { app: './src/main.js', sw: './src/sw.js' }, output: { path: path.resolve(__dirname, '../dist'), filename: '[name].js', publicPath: '/' }, ... plugins: [ ... // service worker caching new SWPrecacheWebpackPlugin({ ... importScripts: [ // use js file generated by webpack { chunkName: 'sw' } ] }) ], ...}
NOTE: if you bump into webpackjsonp is not defined
when webpage trying to include sw.js
, make sure manifest.js
(or you main webpack js) is included before sw.js
.
Register Service Worker
After service-worker.js
is generated, you want to register it. I prefer to embed the javascript code in html (rather than include another javascript for registration).
(function() { if('serviceWorker' in navigator) { navigator.serviceWorker.register('/service-worker.js'); }})();
NOTE: refer to service worker registration code from sw-cache or vuejs-templates/pwa.
NOTE: it's best to put your /service-worker.js
at root path due to scope. If you use /static/js/service-worker.js
, it won't work when your current page path is /
.
NOTE: You probably want to configure your webserver not to cache the service-worker.js
file (refer to this and this).
Below is a sample nginx configuration for no caching.
location /service-worker.js {
alias /myapp/static/js/service-worker.js;
expires -1;
}
Use Chrome DevTools
Your sw-precache-webpack-plugin
configuration should be complete now (assuming you already configured the web app manifest). Use Chrome DevTools and Lighthouse to verify if everything is running properly.
Chrome DevTools -> Application
, checkApplication/Service Workers
andCache/Cache Storage
.Chrome DevTools -> Audits -> Perform an audit -> Progressive Web App -> Run audit
NOTE: you might want to look into Workbox by Google or Service Worker Toolchain by Pinterest.
References: