To implement Code splitting with Webpack, you have three options to choose from:
The available approaches for code splitting are as follows:
- Entry Points: Manually split code using entry configuration.
- Prevent Duplication: Use the SplitChunksPlugin to dedupe and split chunks.
- Dynamic Imports: Split code via inline function calls within modules.
If the high level modules (cms.js
, newsletter.js
, ...) are independent from each other and only rely on generic.js
Directory Structure
src/
├── cms/
│ ├── index.ts
│ ├── ...
├── newsletter/
│ ├── index.ts
│ ├── ...
└── generics/
├── index.ts
├── messages.ts
├── dialogs.ts
src/generics/dialogs.ts
export function open(title: string) {
console.log('Opening dialog : ', title);
}
src/generics/messages.ts
export function alert(msg: string) {
console.log('alert : ', msg);
}
src/generics/index.ts
import * as m from './messages';
import * as d from './dialogs';
export let messages = m ;
export let dialogs = d;
src/cms/index.ts
import { dialogs, messages } from '../generics';
messages.alert('CMS started ...');
src/newsletter/index.ts
import { dialogs, messages } from '../generics';
messages.alert('Newsletter started ...');
Webpack Code splitting
1. Entry Points
This is the simplest and most intuitive way to split code.
However, it requires manual effort and has some drawbacks.
In your config file, declare your modules manually using the entry
object:
// webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: {
'newsletter': './src/newsletter/index.ts',
'cms': './src/cms/index.ts',
},
module: {
rules: [
{
test: /\.ts?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: [ '.ts', '.js' ]
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: "dist/",
}
};
With this configuration, two modules will be generated in the dist folder:
Asset Size Chunks Chunk Names
cms.bundle.js 4.6 KiB cms [emitted] cms
newsletter.bundle.js 4.64 KiB newsletter [emitted] newsletter
Since the cms
and newsletter
modules depend on the generics
module, it is bundled with them.
2. Prevent Duplication with SplitChunksPlugin
Add the optimization.splitChunks
configuration to the webpack.config.js
file:
optimization: {
splitChunks: {
chunks: 'all',
minChunks: 1,
name: 'generics',
minSize: 10,
}
}
Now the generics
module is in its own chunk (remember to include it in your HTML file), and the build will generate 3 files:
Asset Size Chunks Chunk Names
cms.bundle.js 5.85 KiB cms [emitted] cms
generics.bundle.js 1.61 KiB generics [emitted] generics
newsletter.bundle.js 5.9 KiB newsletter [emitted] newsletter
3. Dynamic Imports
Update src/cms/index.ts
to use dynamic imports:
import(/* webpackChunkName: "generics" */ '../generics').then(generics => {
console.log('Generics module loaded ...');
generics.messages.alert('CMS started ...');
});
Update src/newsletter/index.ts
to use dynamic imports:
import(/* webpackChunkName: "generics" */ '../generics').then(generics => {
console.log('Generics module loaded ...');
generics.messages.alert('Newsletter started ...');
});
You may need to adjust some Typescript compile options and possibly install a polyfill for Promise
:
"module": "esnext",
"lib": [
"es2015"
]
Now you no longer need to explicitly include the generics
module in your HTML file. When the import()
is executed, Webpack will fetch the generics
module from the server and cache it.
I hope this explanation helps you to kick off your project :)
Edit (response to comment):
If the modules are in separate projects, manage dependencies using npm
or yarn
.
In the newsletter
project's package.json
, add
generics
as a dependency.
Use non-relative paths for your import. For example, the dynamic import code will look like this:
import(/* webpackChunkName: "generics" */ 'generics').then(generics => {
console.log('Generics module loaded ...');
generics.messages.alert('Newsletter started ...');
});
To bundle all your code, consider adding a main
module that has dependencies to all other modules. Then in the index.ts
of this main module, import all other modules. This index.ts
should be the entry point in the Webpack config.
Remember, bundling all your code into a single file is not recommended for large single page applications, as it can result in a large file size (>8Mb). Webpack's default performance recommendation is around ~250kB per file.