Webpack Performance optimization

Webpack performance improvement plan collection.

DllPlugin(2020.02.08)

We will inevitably introduce many third-party packages in the process of building a project, and these third-party packages will not change during our project development process, but every time we modify the code, we will repackage it again. Analyze these codes again, which greatly affects efficiency.

So is there any way to make these third-party packages only packaged once?

Webpack officially provides a solution.

The DLLPlugin and DLLReferencePlugin somehow implement the splitting of bundles, while also greatly improving the speed of building.

DllPlugin

This plugin creates a dll-only bundle (dll-only-bundle) in an additional standalone webpack setup. This plugin will generate a file named’manifest.json ', which is used to make DLLReferencePlugin Mapped to related dependencies.

  • ‘Context’ (optional): the context of the request in the manifest file (default is the context of webpack)
  • ‘name’: the function name of the exposed DLL (TemplatePaths: [hash] & [name] )
  • ‘Path’: absolute path to the manifest json file (output file)
1
new webpack.DllPlugin(options);

Create a file named manifest.json under the given path path. This file contains the mapping of requests from require and import to module id. This file will also be used by DLLReferencePlugin.

This plugin works with output.library The combination of options can expose (also called into the global domain) the DLL function.

DllReferencePlugin

This plugin is set up in the main webpack configuration file and references the dll-only-bundle (s) to the required pre-compiled dependencies.

  • ‘Context’: (** absolute path **) The context of the request in the manifest (or content attribute)
  • ‘manifest’: an object containing’content ‘and’name’, or an absolute path to a JSON manifest for loading at compile time (compilation)
  • ‘content’ (optional): request mapping to module id (default is’manifest.content ')
  • ‘name’ (optional): the name of the place where dll is exposed (default is’ manifest.name ') (see externals)
  • ‘scope’ (optional): prefix of content in dll
  • ‘sourceType’ (optional): how dll is exposed (libraryTarget)
1
new webpack.DllReferencePlugin(options);

Mapping dependency names to module IDs by referencing the DLL manifest file, and then requiring them when needed via the built-in webpack_require function

With

Mode (Modes)

This plugin supports two modes, * scoped * and * mapped *.

Scope pattern (Scoped

The contents of the dll can only be referenced under the module prefix. For example, if’scope = “xyz” ‘, the file named’abc’ in this dll can be accessed through’require (“xyz/abc”) ’

[Scope Use Cases] (https://github.com/webpack/webpack/tree/master/examples/dll-user)

Mapping mode (Mapped

The contents of the dll are mapped to the current directory. If a’require 'file matches a file in the dll (after parsing), then the file in the dll will be used.

Since this happens after parsing each file in the dll, the same path must ensure that the user of the dll bundle (not necessarily a human, but some code) has permission to access it. For example, if a dll bundle contains the’loadash ‘library and the file’abc’, then 'require (“lodash”) ’ and’require (“./abc”) 'will not be compiled into the main bundle file, but will be used by the dll.

Usage (Usage)

DllReferencePlugin

webpack.vendor.config.js

1
2
3
4
5
new webpack.DllPlugin({
context: __dirname,
name: '[name]_[hash]',
path: path.join(__dirname, 'manifest.json'),
});

webpack.app.config.js

1
2
3
4
5
6
7
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./manifest.json'),
name: './my-dll.js',
scope: 'xyz',
sourceType: 'commonjs2'
});

Example

webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var path = require("path");
var webpack = require("../../");
module.exports = {
// mode: "development || "production",
resolve: {
extensions: [".js", ".jsx"]
},
entry: {
alpha: ["./alpha", "./a", "module"],
beta: ["./beta", "./b", "./c"]
},
output: {
path: path.join(__dirname, "dist"),
filename: "MyDll.[name].js",
library: "[name]_[fullhash]"
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, "dist", "[name]-manifest.json"),
name: "[name]_[fullhash]"
})
]
};

First, use the above configuration to package, the module in the entry will be packaged, and then DllPlugin will map the packaged file to the module id, and save the mapping relationship into the manifest file

According to the above configuration, the three packages “./alpha”, “./a”, and “module” will be packaged into./dist/MyDll.alpha.js, and the mapping relationship between these three packages will be saved./dist/alpha-manifest.json.

At the same time, the packaged file will be exposed as the file name specified in output.library and imported by the entry html.

At this time, the name attribute of DllPlugin and libray are the same, so the manifest saves the mapping relationship between this library and the three modules.

The same goes for beta in entry.

webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var path = require("path");
var webpack = require("../../");
module.exports = {
// mode: "development || "production",
plugins: [
new webpack.DllReferencePlugin({
context: path.join(__dirname, "..", "dll"),
manifest: require("../dll/dist/alpha-manifest.json") // eslint-disable-line
}),
new webpack.DllReferencePlugin({
scope: "beta",
manifest: require("../dll/dist/beta-manifest.json"), // eslint-disable-line
extensions: [".js", ".jsx"]
})
]
};

At this time, through the above configuration file packaging, when encountering a module to be introduced, it will first go through the DllReferencePlugin plugin to find the module corresponding to the previously packaged manifest, and will not go to the node_modules to find it. If you can’t find it, you can go back to the node_modules to find the packaging, which can effectively improve the packaging speed of third-party packages. You only need to run the packaging once in advance and generate the dll. The next packaging only needs to check the manifest.