Webpack is a powerful tool for bundling JavaScript, but as applications grow larger, optimizing those bundles can become challenging. In the early days of front-end development, bundling everything into a single JavaScript file was the default approach. However, as web applications became more complex, loading a massive single bundle with all the code—whether needed immediately or not—became inefficient. This resulted in longer load times, slower performance, and ultimately, a poor user experience.
To address this issue, code splitting was introduced. Code splitting allows you to break your bundle into smaller, more manageable pieces, loading only the code that's necessary for a given page or feature. This improves performance by reducing the initial load time, avoids duplicate dependencies across modules, and makes your web application more efficient.
Here’s a quick breakdown of how to handle single and multiple entry points with shared modules, and how to avoid duplication in your Webpack setup.
1. Single Entry Point with Shared Modules: No Duplication
Everything is bundled together when you use a single entry point for your Webpack config. If you're using a shared module, like Lodash
, Webpack
will only include it once in the bundle.
File Structure:
/src
/index.js
/lodash-util.js
Module Files
// src/index.js
const lodash = require('lodash');
const welCome = require('./another-module');
const component = () => {
const element = document.createElement('div');
element.innerHTML = lodash.join([welCome(), 'Webpack'], ' ');
return element;
}
document.body.appendChild(component());
// src/another-module.js
const lodash = require('lodash');
const welCome = () => lodash.join(['Greetings', 'from'], ' ');
module.exports = welCome;
Webpack Configuration
module.exports = {
entry: './src/index.js', // Single entry point
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new BundleAnalyzerPlugin(), // Analyze the bundle
],
};
What Happens?
Webpack
bundles everything into a singlebundle.js
.There is no duplication of shared modules like
Lodash
.Lodash
will only appear once in the bundle.The Bundle Analyzer shows a clean, single chunk with no repeats.
WebPack Bundle Analyzer Output
Even though both index.js
and another-module.js
are using the same lodash.js
library, Webpack handles it properly and does not duplicate lodash.js
in each module.
Key Takeaway
A single entry point keeps things simple. Dependencies like Lodash
are only included once in the final bundle.
2. Multiple Entry Points: Duplication Happens
If you decide to use multiple entry points, like index.js
and another-module.js
, Webpack will bundle them separately. If both entry points depend on the same module, like Lodash
, you’ll get duplicate Lodash in each bundle.
Example Project Structure
/src
/index.js
/another-module.js
/lodash-util.js
Module Code
// src/index.js
const lodash = require('lodash');
const component = () => {
const element = document.createElement('div');
element.innerHTML = lodash.join(["Hello", 'from', 'Webpack'], ' ');
return element;
}
document.body.appendChild(component());
//______________________________________________
// src/another-module.js
const lodash = require('lodash');
const welCome = () => lodash.join(['Greetings', 'from'], ' ');
module.exports = welCome;
If we look at the code, we have two modules (index.js
and another-module.js
), both of which import the same lodash
module. However, since we are creating separate bundles for index.js
and another-module.js
, they will not import functions from each other. This is because each bundle is independent, and the modules do not share a runtime environment or scope to directly access each other's internal functions.
Webpack Configuration
module.exports = {
entry: {
/**
* Multiple entry points
*/
index: './src/index.js',
another: './src/another-module.js',
},
output: {
/**
* using [name] to generate multiple bundles
*/
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
/**
* using BundleAnalyzerPlugin to analyze the bundle size
*/
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
reportFilename: 'bundle-analyzer-report.html',
})
],
};
What Happens?
Webpack creates two separate bundles:
index.bundle.js
andanother.bundle.js
.Lodash is included in both bundles, leading to duplication.
The Bundle Analyzer report will show Lodash in both bundles.
WebPack Bundle Analyzer Output
Looking at this bundle analyzer output, we can see that the lodash.js
module is duplicated in each entry point bundle.
Key Takeaway
With multiple entry points, Webpack will bundle each entry separately. This can lead to duplicate dependencies being included in each bundle.
3. Avoiding Duplication with splitChunks
To prevent duplicate modules, you can use splitChunks
optimization. This tells Webpack to extract shared modules (like Lodash) into a common chunk that can be shared across all entry points.
Example Project Structure
bashCopy code/src
/index.js
/another-module.js
/lodash-util.js
Module Code
// src/index.js
const lodash = require('lodash');
const result = welCome();
const component = () => {
const element = document.createElement('div');
element.innerHTML = lodash.join(["Hello", 'from', 'Webpack'], ' ');
return element;
}
document.body.appendChild(component());
//______________________________________________
// src/another-module.js
const lodash = require('lodash');
const welCome = () => lodash.join(['Greetings', 'from'], ' ');
module.exports = welCome;
Webpack Configuration
const path = require('path');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
module.exports = {
entry: {
/**
* Multiple entry points
*/
index: './src/index.js',
another: './src/another-module.js',
},
output: {
/**
* using [name] to generate multiple bundles
*/
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
/**
* using BundleAnalyzerPlugin to analyze the bundle size
*/
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
reportFilename: 'bundle-analyzer-report.html',
})
],
optimization: {
/**
* using splitChunks to split common modules into separate bundles
*/
splitChunks: {
chunks: 'all',
},
},
}
What Happens?
Webpack now creates three bundles:
index.bundle.js
,another.bundle.js
, and a shared chunk (e.g.,vendors~index~another.js
).Lodash is extracted into the shared chunk and no longer duplicated in the individual entry point bundles.
The Bundle Analyzer shows Lodash only in the shared chunk.
WebPack Bundle Analyzer Output
Now both index.js
and another-module.js
share the same lodash.js
module.
Key Takeaway
By using splitChunks
, Webpack extracts common modules into a shared chunk, preventing duplication and improving overall performance.
Conclusion
Webpack's code splitting helps you optimize your bundles and avoid duplicate dependencies. Here's a quick recap:
Single entry point: Everything is bundled into one file, with no duplication of shared modules.
Multiple entry points: Webpack creates separate bundles for each entry point, leading to duplicate modules if they share dependencies.
splitChunks
optimization: This extracts shared modules into their own chunk, eliminating duplication and improving performance.
Bundle Analyzer is a great way to visualize how Webpack splits your code and check for any unwanted duplication.
If you'd like to experiment with the code, feel free to pull it and run it on your local machine. GitHub - branch: code-splitting
Happy Coding 👨💻
— Basavaraj Patil