<aside> 🧑🎓 To remove unwanted modules, we must make sure module is indeed unwanted:
How to inspect bundle contents?
</aside>
To remove an unwanted modules means to de-prioritize the module, by moving from critical chunk, to a noncritical one. To achieve it, the following actions are required:
To find why is a module included in a bundle, the Webpack compilation stats are required. To generate them, build the application with corresponding flag:
yarn build --stats # using Yarn
npm run build -- --stats # using NPM
<aside> 🧠
Alternatively, try using https://statoscope.tech/ to get a UI to play around with!
</aside>
The build/bundle-stats.json will be generated as a result. Next, add the reason-finding utility to the root of your project. Create a reason.js file and paste the following content:
const fs = require('fs');
const path = require('path');
const moduleNameToLookup = process.argv[2] || 'CategoryPage.container.js';
console.log(`lookup of "${moduleNameToLookup}"...`)
console.log()
const statsPath = path.resolve(__dirname, './build/bundle-stats.json');
const stats = JSON.parse(fs.readFileSync(statsPath));
console.log('NOTE: preview is generated from compiled source, original module contents may differ.')
stats.modules.forEach((module) => {
const { name, reasons, chunks } = module;
if (!name.includes(moduleNameToLookup)) {
return;
}
const pChunks = chunks.map((chunk) => {
const { names, files } = stats.chunks[chunk];
const fileNames = files.map(file => file.split('/').slice(-1)[0]).join(', ');
if (!names) {
return `${fileNames}`;
}
return `${fileNames} (part of ${names.map(name => `${name}`)} chunk group)`;
});
console.log('\\n' + Array.from({ length: 30 }, () => '=/').join('') + '\\n');
console.log('File:');
console.log(`\\t${name}`)
console.log();
console.log(`Chunks:`);
pChunks.forEach((pChunk, i) => {
console.log(`\\t ${i}. ${pChunk}`);
});
const validReasons = reasons.reduce((acc, reason) => {
const { loc, moduleName } = reason;
const reasonModule = stats.modules.find((module) => module.name === moduleName);
if (!reasonModule || !loc) {
// skipping if no module or no location
return acc;
}
const [lineFrom, rest] = loc.split(':');
const [charFrom, charTo] = rest.split('-');
const lines = reasonModule.source.split('\\n');
const segment = lines.slice(lineFrom - 1).join('\\n');
const preview = segment.slice(charFrom, charTo);
if (!preview.includes('export') && !preview.includes('import')) {
// skipping if preview does not contain any import / export
return acc;
}
const isReasonAlreadyIncluded = acc.some((otherReason) => (
otherReason.preview === preview
&& otherReason.moduleName === moduleName
));
if (isReasonAlreadyIncluded) {
return acc;
}
return [
...acc,
{
preview,
moduleName,
}
]
}, []);
validReasons.forEach((reason, i) => {
const { type, moduleName, preview } = reason;
console.log('\\n' + Array.from({ length: 60 }, () => '-').join('') + '\\n');
console.log(`${i + 1}. reason`);
console.log();
console.log(`File: ${moduleName}`);
console.log(`Preview: ${preview}`);
});
})
Next, run it, passing the module reason of which inclusion into the bundle we are interested to find:
node reason.js CategoryPage.container.js
It will output the similar result:
<aside> 🧠 If the imports of a module do not lead you anywhere directly, try searching for one of the reasons (reason file name) of a module of interest.
</aside>

<aside>
🧠 Static import is an import made using import A from B syntax. For example:
import { CATEGORY } from 'Component/Header/Header.config';
Dynamic import is an import made using import(A) syntax. For example:
const CartDispatcher = import(
/* webpackMode: "lazy", webpackChunkName: "cart" */
'Store/Cart/Cart.dispatcher'
);
The magic comments (i.e. webpackChunkName) are commonly used to hint Webpack a name of a chunk group to place a module into.
</aside>
If the module is included in a bundle, likely, it is statically imported in it. The goal is to transform these static imports into dynamic ones.
<aside> 🧠 All imports of a module must be dynamic for it to be moved into another chunk, if one of many will be dynamic, the module might become duplicated across chunks!
</aside>