Currently the chunk manifest is always inlined into generated html files. It's ok if there are not that many pages/chunks, but in my prototype with ~500 pages the uncompressed chunk-manifest.json file has already size of ~30kB (12kB gzipped) and I can assume that with ~5000 pages that we got in total, it will be ~10x larger.
That's why it might be a good idea to add an option to generate a chunk-manifest.js file and a script tag with src attribute pointing to it.
So far I came up with something like this:
This generates chunk-manifest.js file based on contents of chunk-manifest.json file:
// /src/utils/webpack.config.js
new ChunkManifestPlugin({
filename: `chunk-manifest.json`,
manifestVariable: `webpackManifest`
}),
{
apply: function (compiler) {
compiler.plugin(`emit`, function (compilation, callback) {
compilation.assets[`chunk-manifest.js`] = new ConcatSource(
`window.webpackManifest = `,
compilation.assets[`chunk-manifest.json`],
`;`
);
callback();
});
}
},
This decides if it should create script tag with inlined contents of chunk-manifest.json file or with src attribute pointing to chunk-manifest.js file:
// /cache-dir/static-entry.js
if (some condition) {
const chunkManifest = require(`!file?name=[name].[hash].[ext]!../public/chunk-manifest.js`)
headComponents.unshift( <
script id = "webpack-manifest"
key = "webpack-manifest"
src = {chunkManifest}
/>
)
} else {
const chunkManifest = require(`!raw!../public/chunk-manifest.json`)
headComponents.unshift( <
script id = "webpack-manifest"
key = "webpack-manifest"
dangerouslySetInnerHTML = {
{
__html: `
//<![CDATA[
window.webpackManifest = ${chunkManifest}
//]]>
`,
}
}
/>
)
}
It's just an initial version, which probably has some issues, e.g. require(!file...) will probably emit chunk-manifest.[hash].js as many times as there are pages (though maybe node caching mechanism kicks in here for require calls and it will do it just once), pathPrefix is not taken into account (though it should be an easy fix) etc.
Please let me know if it's something you'd be interested in and what's the best way to specify an option to decide if chunk manifest should be inlined or not and I'll prepare a PR.
Since the webpack manifest is loaded only once per session and is on the critical path for getting to interactive (better to inline things on critical path as we need them ASAP), we don't want to defer loading the script.
We do want however to move the inlining after the body as the manifest isn't on the critical path for the initial paint so putting it in the head is slowing down the initial paint some. Lemme know if you want to work on that!
@KyleAMathews But wouldn't that mean that:
I'm not asking for it to be the default behavior, just an option that might be useful in cases where there are so many pages. Could it be reconsidered once the inlined manifest is moved to the end or or after the body element?
Hopefully you won't be building 5k page sites before then :-P
Thanks @KyleAMathews for you support, that is awesome news!
@barraq np! Yeah the goal has always been to make Gatsby work for any sized site e.g. 10s of millions of pages even — actually, really want to rebuild Wikipedia on Gatsby someday haha :-)
But yeah, had to ship something first and then go from there but there's straightforward ways to remove all the current scaling problems.
Will be putting together a new roadmap for this stuff in coming weeks.
Most helpful comment