The DllPlugin and DllReferencePlugin provide means to split bundles in a way that can drastically improve build time performance.

DllPlugin

This plugin used in a separate webpack config exclusively to create a dll-only-bundle.

It creates a manifest.json file, which is used by the DllReferencePlugin to map dependencies.

  • context: (optional), context of requests in the manifest file(default to the webpack context).

  • name: name of the exposed dll function(TemplatePaths: [hash] & [name])

  • path: absolute path to the manifest json file(output)

1
new webpack.DllPlugin(option)

Creates a manifest.json which is written to the given absolute path.

It contains mappings from require and import requests, to module ids. It is used by the DllReferencePlugin.

Combine this plugin with output.library option to expose(aka, put into the global scope) the dll function

output.library expose the name to global scope

DllReferencePlugin.name add the name to the mapping file.

So it’s important to keep output.library and DllReferencePlugin.name same to set a right mapping.

DllReferencePlugin

This plugin is used in the primary webpack config, it references the dll-only-bundle to require the pre-built dependencies.

  • context: absolute path, context of the requests in the manifest(or content property)

  • manifest: an object containing content and name or a string to the absolute path of the JSON manifest to be loaded upon compilation.

  • content: (optional), the mappings from request to module id(default to manifest.content)

  • name: (optional), the name where the dll is exposed (default to manifest.name)

  • scope: (optional), prefix which is used for accessing the content of the dll

  • sourceType: (optional), how the dll is exposed.

1
new webpack.DllReferencePlugin(options)

References a dll manifest file to map dependencies names to module ids, then requires them as needed using the internal __webpack_require__ function.

Note: Keep the name consistent with output.library

Modes

This plugin can be used in two different modes, scoped and mapped.

Scoped Mode

The content of the dll is accessible under a module prefix, i.e. with scope = 'xyz' a file named abc in the dll can be access via require(xyz/abc).

Mapped Mode

The content of the dll is mapped to the current directory. If a required file matches a file in the dll(after resolving), then the file from the dll is usd instead.

Because this happens after resolving every file in the dll bundle, the same paths must be available for the consumer of the dll bundle, i.e. if the dll contains lodash and the file abc, require('lodash') and require('./abc') will be used from the dll, rather than building them into the main bundle.

1
2
3
4
5
6
// webpack.config.dll.js
new webpack.DllPlugin({
context: __dirname,
name: '[name]_[hash]',
path: path.join(__dirname', 'manifest.json'),
})
1
2
3
4
5
6
// webpack.config.base.js
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./manifest.json'),
name: './my-dll.js',
})

Notes

Output.library and DllPlugin.name

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
output: {
path: path.resolve(__dirname, 'lib'),
filename: '[name]_[hash].js',
library: '[name]_[hash]', // this set the exposed function name to [name]_[hash]
},
plugins: [
new webpack.DllPlugin({
path: path.resolve(__dirname, 'lib', '[name]-manifest.json'), // put the manifest file in lib directory
name: '[name]_[hash]', // be consistent with library name to make the map correct
context: __dirname,
})
]
}

Context in Dev Config

Set the DllReferencePlugin.context same as DllPlugin.context so the manifest will bundle and resolve the dll files from the same root directory.

Add dll bundle to html

After bundle the dll, I should insert it betore app.js in the html file to provide the global function.

  • Step 1: Copy the dll files to the dist directory

I use the copy-webpack-plugin plugin

1
2
3
4
// webpack.config.js
new CopyPlugin([
{ from './lib/*.js' } // default to output.path, so the dll file will be copied to output.path/lib/*.js
])
  • Generate a manifest of the dll files for html-webpack-plugin to insert to the template

I use the webpack-manifest-plugin

1
2
// webpack.config.dll.js
new ManifestPlugin()

It will generate the manifest.json in output.path

1
2
3
{
"vendor.js": "vendor_0642aa84a6959d661519.js"
}
  • Insert the Manifest into the html
1
2
3
4
5
6
7
8
9
//parse the json
const fs = require('fs)
const manifest = JSON.parse(fs.readFileSync(require('./lib/manifest.json')))

// insert
new HtmlPlugin({
//...
dll: `./lib/${manifest['vendor.js']}`, // the dll file locates at ./lib/*.js
})

Summary

Dll Config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const webpack = require('webpack')
const path = require('path')
const ManifestPlugin = require('webpack-manifest-plugin')

module.exports = {
entry: {
vendor: ['./src/vendor'],
},
output: {
filename: '[name]_[hash].js',
path: path.resolve(__dirname, 'lib'),
library: '[name]_[hash]',
},
plugins: [
new webpack.DllPlugin({
name: '[name]_[hash]',
path: path.resolve(__dirname, 'lib', '[name]-manifest.json'),
}),
new ManifestPlugin(),
],
}

Dev Config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const webpack = require('webpack')
const path = require('path')
const HtmlPlugin = require('html-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin')
const fs = require('fs')

const manifest = JSON.parse(fs.readFileSync('./lib/manifest.json'))

module.exports = {
entry: {
app: ['./src/index'],
},
output: {
filename: 'scripts/[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new HtmlPlugin({
template: path.resolve(__dirname, 'src', 'templates', 'index.html'),
title: 'dev',
dll: `./lib/${manifest['vendor.js']}`,
}),
new webpack.DllReferencePlugin({
context: '.',
manifest: require('./lib/vendor-manifest'),
}),
new CopyPlugin([
{ from: './lib/*.js'}
]),
]
}