-
Notifications
You must be signed in to change notification settings - Fork 799
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
webpack plugin does not respect splitChunks
#1859
Comments
Apologies that you're running into this. CC: @developit for visibility, as he's looking into a revamp of the To aid in reproducing this on our end, could you share either a link to your project's config (if it's publicly available) or alternatively share a snippet of your relevant |
Do you have any thoughts on whether this is a bug workbox needs to fix, or something else? We're keen to use this for the Unsplash PWA but a bit stuck on this at the moment |
Thanks for the reproduction—I'm investigating now to see if there are any workarounds using the current |
The We read those workbox/packages/workbox-webpack-plugin/src/lib/get-manifest-entries-from-compilation.js Line 69 in b146d8d
I'm not sure if there's a better way of getting those In your reproduction, the You have a couple of options right now:
Code to automate the second option could look like:
You might have already considered the second option, based on this:
From your simple reproduction, I only see |
I will read your answer in detail tomorrow, but to answer this question quickly:
One example: |
Thanks for that production context. It sounds like constructing Reading up on So, I think that the current status is that it would be difficult to use the The most promising approach might end up being using the |
If it helps, we have a similar problem with server-side rendering: we need to know all the chunks that were referenced in a server-side render, so that we can include the necessary I believe the project webpack-flush-chunks essentially provides us with a function that converts There are projects of a similar nature which I believe also have to solve this problem, e.g. https://github.com/smooth-code/loadable-components/blob/69dbb8b2b1f32da9bcac7b91515b81f7339f68a4/packages/server/src/ChunkExtractor.js#L138. |
@OliverJAsh, if it's helpful, I use Once you have a manifest of output files, it's relatively straightforward to write a task to run either If you want to try a custom approach like that, I'd be happy to help until we can get these issues resolved in the next version of the webpack plugin. |
How would you use that approach to selectively whitelist chunks whilst also including any split chunks which relate to the whitelisted chunks? For example, if I had two chunks, foo and bar, and I only whitelisted foo, I would also want to include the split chunks for foo, e.g. vendors~foo. |
I'd probably just use a regular expression (or a filter function) that iterates through each of the assets and only returns the ones I wanted to precache. When you use the Am I understand your question correctly? Here's an example of how I use cacheGroups: {
npm: {
test: /node_modules/,
name: (mod) => {
const pkgName = mod.context.match(/node_modules\/([^/]+)/)[1];
return `npm.${pkgName}`;
},
},
}, It produces the following assets for me:
|
Thanks @philipwalton. I'll give that a try. Right now I'm thinking of something like the following: const whitelistedChunkNames = ['main', 'vendors'];
const assetsToPrecache = assets.filter(asset => {
const chunkNames = asset.split('~');
return chunkNames.some(chunkName => whitelistedChunkNames.includes(chunkName))
}); Is this something the |
@jeffposnick Could we extract this information from {
"entrypoints": {
"main": {
"chunks": [
1,
0
],
"assets": [
"vendors~main.js",
"main.js"
],
"children": {},
"childAssets": {}
}
},
"namedChunkGroups": {
"main": {
"chunks": [
1,
0
],
"assets": [
"vendors~main.js",
"main.js"
],
"children": {},
"childAssets": {}
}
}
} I believe this is how other tools do it:
|
Thanks for all those references. I definitely think we should follow their lead in a future revision of the plugin to support this without manual configuration as much as possible. In the meantime, have you had any luck using |
@jeffposnick I'm experimenting with a filter over const whitelistedChunkNames = ['main'];
const filteredPrecacheManifest = self.__precacheManifest.filter(({ revision, url: pathname }) => {
const pathnameParts = pathname.split('/');
const assetFileName = pathnameParts[pathnameParts.length - 1];
const chunkNames = assetFileName
// Remove `chunkhash` + file extension
.replace(/\..+\.(js|css)$/, '')
// Chunk names are delimited by `~` character
.split('~');
console.log({ pathname, chunkNames });
const doesRelateToWhitelistedChunk = chunkNames.some(chunkName =>
whitelistedChunkNames.includes(chunkName),
);
return doesRelateToWhitelistedChunk;
});
console.log({ filteredPrecacheManifest }); One caveat I'm just thought of however is that I'm not sure if webpack truncates the file names. In which case, there would be no guarantee the chunk name would appear in the asset file name. |
IIUC, the same caveat would apply to the |
I don't believe it does, but you could run it in production mode to confirm. If they change in the future that'd be a breaking change. |
The example I posted earlier appears like it might be truncated. Notice the |
Wow, that's quite the filename! :) |
Unfortunately this means we're now blocked by this issue. If there's any more information I can provide, I would be happy to help. |
So, it's unlikely that we're going to come up with a formal solution to this prior to some of the work that @developit has planned for refactoring the One path forward right now could be to forgo using the I just tried modifying your earlier reproduction project by putting in a two-step build:
and then created a
The difference here is that you're just relying on matching against files located on disk following the successful You'd want to your
|
@jeffposnick Thanks for your continued support on this!
Won't this suffer from the same problem with regards to truncated file names? The globs might not find a match if the chunk name has been truncated from the generated asset's file name. |
I was under the impression that the values in the The general idea is that you can read in the full compilation stats after-the-fact and look at whatever properties make the most sense for your use case. If it's not that particular property, then presumably the filenames you're after are stored somewhere else in compilation stats. Despite the |
@jeffposnick That does make sense, thanks! I'll give it a shot. |
Great—sorry that this is currently a hassle. It's a good piece of feedback for how we can improve the default |
Got this working! 🎉 Two other things I had to do:
const flatten = require('lodash/flatten');
const path = require('path');
const { injectManifest } = require('workbox-build');
const compilationStats = require('./stats.json');
const chunksToPrecache = ['main'];
const globPatterns = flatten(
chunksToPrecache.map(chunkName => compilationStats.namedChunkGroups[chunkName].assets),
);
const { outputPath } = compilationStats;
const globDirectory = outputPath;
const swSrc = 'CHANGEME';
const swDest = 'CHANGEME';
const { publicPath } = compilationStats;
const prependPublicPathToManifestEntries = originalManifest => {
const manifest = originalManifest.map(entry => ({
...entry,
url: path.join(publicPath, entry.url),
}));
return { manifest };
};
const manifestTransforms = [prependPublicPathToManifestEntries];
injectManifest({
swSrc,
swDest,
globPatterns,
manifestTransforms,
}).then(({ count, size }) => {
console.log(`Generated ${swDest}, which will precache ${count} files, totaling ${size} bytes.`);
}); |
This should be addressed by the current Workbox v5.0.0 alpha. |
@OliverJAsh—Just wanted to confirm that you've had a chance to test |
Hey! Yup it fixes it. Test case here. Thank you. 😃 |
With minChunks: 3, webpack 4 generated default~ and vendors~ chunks. InjectManifest doesn't see default chunk, even with all js included. |
OMG this OPTIONAL parameter maximumFileSizeToCacheInBytes just ruined few hours of my life because I have 2.2mb raw common chunk and it's doesn't included until I have to set this OPTIONAL . |
(I'm definitely sorry about this frustration—the |
Library Affected:
workbox-webpack-plugin
Issue or Feature Request Description:
I have enabled webpack's
splitChunks
option. This splits my chunks so that "vendor" imports are stored in a separate asset. For example, themain
chunk will result in two assets:main.js
andvendors~main.js
.When I use
InjectManifest
'schunks
option to whitelist themain
chunk, I expect it to include all the assets relating to this chunk. In this case, that would bemain.js
andvendors~main.js
.However, it does not seem to respect the vendor asset created by
splitChunks
—it only includesmain.js
.It is not feasible for me to list these manually, because webpack may create any number of vendor assets, depending on the common module imports between all my chunks.
The text was updated successfully, but these errors were encountered: