Manifest Plugin
Examine the asset maps builder and Webpack chunk trackers used to compile file dependency manifests.
Key File Location: ./dinou/webpack/plugins/manifest-generator-plugin.js💡 Overview
To resolve hashed javascript paths (e.g. main.a1b2c3d4.js) during page rendering and server function postbacks, the loader needs to keep compile mappings in sync. This plugin crawls Webpack compilation outputs to build a chunk dependency index.
The plugin hooks into Webpack's asset analysis step (PROCESS_ASSETS_STAGE_ANALYSE). It traverses all output chunks, resolves their names, matches them to output filenames on disk, and writes them to the manifest data:
📊 Manifest Generator Flow
The flowchart below shows how compilation chunks are crawled and output mapped to manifest.json:
🎯 Manifest Consumers
The emitted manifest.json file is consumed by core subsystems to resolve cache-busted filenames:
- HTML SSR Renderer (
render-html.js): When compiling the initial HTML response, the server imports thegetAssetFromManifesthelper to map logical assets (likemain.jsanderror.js) to the compiled, hashed file names on disk. - Webpack Plugins (
ServerFunctionsPlugin): During building, plugins read the in-memory objectmanifestGeneratorPlugin.manifestDatato replace temporary placeholders (like__SERVER_FUNCTION_PROXY__) with their finalized production hashes.
⚙️ Complete Code Walkthrough
Below is the full code of the Webpack manifest generator plugin:
// manifest-generator-plugin.js
class ManifestGeneratorPlugin {
constructor() {
this.manifestData = {}; // same as in Rollup
}
apply(compiler) {
const pluginName = "ManifestGeneratorPlugin";
compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
const { Compilation } = compiler.webpack;
// Run when all assets are ready
compilation.hooks.processAssets.tap(
{
name: pluginName,
stage: Compilation.PROCESS_ASSETS_STAGE_ANALYSE,
},
(assets) => {
// Traverse chunks to generate manifest
for (const chunk of compilation.chunks) {
if (!chunk.name) continue; // only chunks with a name
for (const file of chunk.files) {
if (file.endsWith(".js")) {
const cleanName = chunk.name + ".js"; // same as Rollup
this.manifestData[cleanName] = file; // hashed JS file
}
}
}
// Emit manifest.json
const json = JSON.stringify(this.manifestData, null, 2);
compilation.emitAsset(
"manifest.json",
new compiler.webpack.sources.RawSource(json)
);
}
);
});
}
}
module.exports = new ManifestGeneratorPlugin();