In my current project using webpack with (workbox-webpack-plugin
) and workbox (with workbox-window
) I have encountered an error where the serviceworker will never respond to messages when the page is loaded at a "deep url", like "/my-path/is-nested".
It will work on "/my-path".
In a minimal reproducible environment, this is supposed to happen.
https://my-app.my-name.company-dev-envs.cloud/some-unique-id
).register()
)messageSW
is used to ask for the SWs "version"event.ports[0].postMessage
with a string indicating the versionIs the site accessed in a "deep" path, like /some-unique-id/test, the messaging will never work.
Workbox does successfully "register" - but no events will be fired (except externalactivated
when Update on Reload
in the Application > Service Worker Tab is selected)
The serviceworker will be reported as "active and running" with no other service workers displayed. It seems to handle fetches okay too. Only messages and events never respond/fire via the wb
Workbox Window instance.
The "application" tab reports the service worker as active and running:
index.js (main entry for application)
/* globals window, System */
import './offline';
// [...]
offline.js
import { Workbox } from 'workbox-window';
if ('serviceWorker' in navigator) {
const wb = new Workbox('./sw.js');
const attachDebugEventHandlers = (events) => {
events.forEach((eventName) => {
wb.addEventListener(eventName, () => {
console.log(`[workbox sw] ${eventName} triggered`);
});
});
};
attachDebugEventHandlers([
'activated',
'controlling',
'externalactivated',
'externalinstalling',
'externalwaiting',
'installed',
'message',
'redundant',
'waiting',
]);
wb.register()
.then((registration) => {
console.log('workbox sw register successful');
console.log("sending message")
wb.messageSW({ type: 'GET_VERSION' }).then((ver) => console.log(`[workbox sw] version reported as ${ver}`))
})
.catch((err) => {
console.error('[workbox sw] could not activate sw', err);
});
sw.js
const SW_VERSION = '1.0.0';
console.log("sw loaded")
import {createHandlerBoundToURL, precacheAndRoute} from 'workbox-precaching';
import { NavigationRoute, registerRoute } from 'workbox-routing'
// auto generate from webpack manifest
precacheAndRoute(self.__WB_MANIFEST, {
// Ignore all URL parameters.
ignoreURLParametersMatching: [/.*/] // main.js is loaded with a version hash
});
self.addEventListener('message', event => {
console.log(`[Message] event: `, event.data);
});
self.addEventListener('install', function(event) {
event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim())
})
addEventListener('message', (event) => {
console.log("message")
if (event.data && event.data.type) {
if (event.data.type === 'GET_VERSION') {
event.ports[0].postMessage(SW_VERSION);
}
}
})
const handler = createHandlerBoundToURL('/index.html');
const navigationRoute = new NavigationRoute(handler);
registerRoute(navigationRoute);
webpack.config.js (shortened for brevity)
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WorkboxPlugin = require('workbox-webpack-plugin');
module.exports = {
devtool: 'eval-source-map',
module: {
rules: [
{
test: /\.(jsx?)$/,
include: [
path.resolve(__dirname, 'src'),
],
use: ['babel-loader'],
},
// [...] (style loading)
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
},
],
},
],
},
devServer: {
historyApiFallback: true,
disableHostCheck: true
},
plugins: [
// [...]
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'src/html/index.html')
}),
// [...]
new WorkboxPlugin.InjectManifest({
swSrc: './src/sw.js',
swDest: 'sw.js',
maximumFileSizeToCacheInBytes: 12 * 1024 * 1024,
}),
],
};
Versions used:
"webpack": "^4.33.0",
"webpack-cli": "^3.3.2",
"workbox-window": "^5.1.3"
"workbox-webpack-plugin": "^5.1.3"
I was able to solve it myself. The issue was of course that the path to ./sw.js
is not correct when the user navigates to a subpath.
https://my-website.com/a-subpath/a-resource
does not resolve ./sw.js
to https://my-website.com/sw.js
but rather to https://my-website.com/a-subpath/sw.js
This was a very dumb mistake but hopefully somebody can be helped with this answer. Perhaps it would be helpful if workbox-window
didn't resolve correctly as if the registration were a success, but rejected the ./sw.js
path.