workbox icon indicating copy to clipboard operation
workbox copied to clipboard

Inject manifest option swDest should probably support [contenthash] name template

Open jdmerinor opened this issue 3 years ago • 2 comments

Library Affected: workbox-webpack-plugin

Browser & Platform: Windows with Webpack 4 and 5

Issue or Feature Request Description: Hi guys, I'm trying to do some server-side modifications to the precache based on what module the user is visiting. So the actual JS that I'm returning as my SW script is something like this:

importScripts('path/to/my/swDest');
self.functionExposedByMySwDest(serverInjectedParams);

So the issue that I'm facing is that in this case if the swDest script changes I don't have a way of busting it from the cache. So I thought, surely I can just do something like this in my webpack build to generate it with a proper hash:

new InjectManifest({
	swSrc: './JS/sw-entry.js',
	swDest: 'service-worker.[contenthash].js',
	otherOptions....
}),

But it actually fails in here because it fails to get the asset from webpack: https://github.com/GoogleChrome/workbox/blob/v6/packages/workbox-webpack-plugin/src/inject-manifest.js#:~:text=const%20swAsset%20%3D%20compilation.getAsset(config.swDest)%3B image

I guess I could come up with something that after the asset is emitted I can just add the hash to it or something like that but it just seems wrong I guess. And what seems more interesting is that I think this is the only place with the problem because the asset is actually being emitted properly as I can see the asset is there with the correct hash: image

Thanks and please let me know if I can help with better details :)

jdmerinor avatar Jan 17 '22 06:01 jdmerinor

it's important to note that these modifications are not known at build time unfortunately, hence the need of doing them on the server-side instead of being able to use the manifestTransforms or the additionalEntries option.

jdmerinor avatar Jan 17 '22 19:01 jdmerinor

Generally speaking, it's a best practice to keep the same URL for your service worker across deployments. I understand that in your specific use case, the top-level service worker would have the same name, and it would in turn call importScripts() on the URL emitted from webpack (though I'm not sure how you would get that importScripts() call updated...), but I worry that adding in support for [contenthash] would lead to other folks not following the best practice.

One of the things you can do is the set updateViaCache: 'all' when registering your service worker, to ensure that a network freshness check is made against the URL that you pass to importScripts(), without having to add a hash to it.

Another thing you could do, if you really do need server-side control (I'm not actually sure how the server-side of things comes into play based on your description) is to include something like:

const serverManifest = {% serverProvidedManifest %};
const compositeManifest = serverManifest.concat(self.__WB_MANIFEST);
precacheAndRoute(compositeManifest);

I.e. use some server-side logic to sub in whatever templated value you want for {% serverProvidedManifest %} and then ultimately pass that to precacheAndRoute().

Finally, you could just do the manual renaming that you suggest.

jeffposnick avatar Jan 18 '22 21:01 jeffposnick