The Webpack DLL plugin is often misunderstood as just another way to speed up builds; in reality, it fundamentally changes how Webpack processes your vendor dependencies by pre-compiling them into separate, immutable bundles.
Let’s see it in action. Imagine a typical React application where react and react-dom are your primary vendor dependencies.
First, you set up a webpack.dll.config.js file. This configuration is separate from your main application build.
// webpack.dll.config.js
const path = require('path');
const DllPlugin = require('webpack').DllPlugin;
module.exports = {
mode: 'production',
entry: {
vendor: [
'react',
'react-dom',
'lodash' // Adding another common dependency
]
},
output: {
path: path.resolve(__dirname, 'dll'),
filename: '[name].dll.js',
library: '[name]_library' // This name is crucial for the main config
},
plugins: [
new DllPlugin({
path: path.resolve(__dirname, 'dll', '[name]-manifest.json'),
name: '[name]_library' // Must match output.library
})
]
};
You then run this configuration:
npx webpack --config webpack.dll.config.js
This creates two things in your dll directory:
vendor.dll.js: The actual pre-compiled JavaScript bundle containingreact,react-dom, andlodash.vendor-manifest.json: A JSON file mapping the original module names (e.g.,'react') to their corresponding entry points within thevendor.dll.jsbundle.
Now, in your main webpack.config.js, you tell Webpack to use these pre-compiled DLLs and not to process them again.
// webpack.config.js (snippet)
const path = require('path');
const DllReferencePlugin = require('webpack').DllReferencePlugin;
module.exports = {
// ... other main config
plugins: [
new DllReferencePlugin({
context: __dirname, // Usually the project root
manifest: require('./dll/vendor-manifest.json') // Points to the manifest file
}),
// ... other plugins
],
// ...
};
When you run your main Webpack build (npx webpack), it sees the DllReferencePlugin. Instead of trying to find and bundle react, react-dom, or lodash from node_modules, it consults the vendor-manifest.json. It learns that these modules are already available in the vendor.dll.js bundle (which you’d typically include as a <script> tag in your HTML or via another mechanism). Webpack then just adds a reference to the vendor_library global, effectively saying, "Hey, this stuff is already loaded, don’t worry about it."
The core problem the DLL plugin solves is the time spent repeatedly bundling your stable, infrequently changing vendor dependencies on every build. Think of react, react-dom, lodash, or UI component libraries. These rarely change week-to-week. Your application code, however, changes constantly. By pre-compiling the vendor code into a separate, immutable bundle, Webpack only needs to re-process your application code.
Internally, DllPlugin generates a manifest file that acts as a lookup table. When DllReferencePlugin is used, it reads this manifest. If it encounters an import 'react' in your application code, it checks the manifest. If react is listed as part of the vendor DLL, Webpack instructs the loader system to essentially ignore the import statement in terms of bundling and instead rely on a global variable (defined by output.library in the DLL config) that exposes the pre-compiled vendor code. This means your main Webpack build becomes significantly faster because it skips the entire process of resolving, parsing, and bundling these large, stable dependencies.
The "cache" aspect is that once vendor.dll.js and vendor-manifest.json are generated, they are only re-generated if the webpack.dll.config.js or the entry list within it changes. Your main build will then use these unchanged DLL files indefinitely until the DLL configuration itself is modified. This is why it’s particularly effective for large projects with many dependencies that don’t change often.
The most surprising thing about the DLL plugin is that it doesn’t actually bundle your vendor code into your main application’s output. Instead, it creates a completely separate build artifact that your main build references. You are responsible for ensuring that the vendor.dll.js file is loaded into the browser before your application’s main JavaScript bundle. This is often done by adding a <script src="/dll/vendor.dll.js"></script> tag to your index.html file, or by configuring your HTML generation plugin (like HtmlWebpackPlugin) to include it automatically.
The next hurdle you’ll face is managing multiple DLL bundles for different sets of dependencies, or handling dynamic imports within your DLLs.