preface
The use of WebPack plugin DllPlugin and DllReferencePlugin is an important way to optimize packaging speed in front-end engineering. Webpack Chinese-dllPlugin.
They can package commonly used and infrequently updated modules, generate JS and JSON files, and generally place them in a public directory. These dependencies are no longer compiled when the project is packaged, but are read by inserting script tags into the HTML. Common frameworks and libraries such as Vue, ANTD, Echarts, etc. This is especially true when the project depends on packages of a certain size, and the increase in speed is significant.
There are a lot of introductions to the use of plug-ins on the web, but few vue-CLI build projects give a detailed description of the use of plug-ins, as well as the pitfalls and considerations of plug-ins. I also had more or less a problem with configuring this plug-in at work, and I think I’ll have more of these problems in the future.
Vue – webpack in cli
Vue-cli-built projects, by default and simplest, use vue.config.js to configure Webpack, and have their own unique syntax and rules. Webpack related | vue – cli.
The most critical part of the plug-in is in the objects (or function methods) provided by the configureWebpack option. According to the documentation, you need to conditionally configure the behavior based on the environment, or if you want to modify the configuration directly, use the function method (which executes lazily after the environment variable is set). The first parameter to the method receives the parsed configuration. Within a function, you can modify the configuration directly, or return an object that will be merged.
// vue.config.js
module.exports = {
configureWebpack: config= > {
if (process.env.NODE_ENV === 'production') {
// Modify the configuration for the production environment...
} else {
// Modify the configuration for the development environment...}}}Copy the code
DllPlugin configuration
Typically, a new configuration file is specifically used to generate the dependency library files. The plug-in typically generates dependent files at the public/vender directory location in the project.
configuration
webpack.dll.config.js
// Define common objects
const path = require('path')
const webpack = require('webpack')
const CleanWebpackPlugin = require('clean-webpack-plugin')
// Directory for storing DLL files
const dllPath = 'public/vendor'
module.exports = {
// The library file to extract
entry: {
vue: ["vue"."vue-router"."vuex".'axios'].antd: ["ant-design-vue"].echarts: ["echarts"],},output: {
path: path.join(__dirname, dllPath),
filename: '[name].dll.js'.// Global variable name exposed in vendor.dll.js
// Keep the same name as webpack.dllPlugin
library: '[name]_[hash]'
},
plugins: [
// Clear the previous DLL file
new CleanWebpackPlugin(['*. *'] and {root: path.join(__dirname, dllPath)
}),
// Define the plug-in
new webpack.DllPlugin({
path: path.join(__dirname, dllPath, '[name]-manifest.json'),
// keep the same name as output.library
name: '[name]_[hash]'.context: process.cwd()
})
]
}
Copy the code
The main description
- Defining common objects
The clean-webpack-plugin is mainly used to clear the vendor directory first each time a dynamically linked library is generated.
- Directory for storing DLL files
It is generally defined as public/vendor.
Note: You generally place dynamic-linked libraries in the public directory of your project, not dist or any other directory.
- Entry portal
Define which libraries/dependencies to extract.
In this object, the key name defines the prefix to generate the spawn file; The key value is an array type and defines the dependency name. For example, in the code above, “VUE family bucket” is defined as vUE; That definition would have the plug-in generate these dependencies into three files. Three manifest.json files are generated to describe what the dynamic link library contains, and this file is used to map the DllReferencePlugin to the corresponding dependencies.
- The output export
The path option uses NodeJs’s path to build the path (absolute path).
The filename option prefixes the file with the function name of the exposed DLL.
Library This plug-in can be combined with this option to expose (also called put into global scope) DLL functions, consistent with the name in the Dllplugin, where hash values are used to address caching and possible duplication.
- plugins
Define plug-ins.
Path Manifest. json file absolute path (output file).
Name Specifies the function name of the exposed DLL (TemplatePaths: [fullHash] & [name]).
Context (optional) : The context requested in the manifest file (default webpack context), where process.cwd() is used to return the current working directory.
DllReferencePlugin configuration
This plug-in is configured in the main webPack configuration file, and the plug-in references the required pre-compiled dependencies according to the description file to avoid recompiling the dependencies in the common area.
configuration
vue.config.js
module.exports = {
configureWebpack: config= > {
plugins: [...// Avoid recompiling dependencies in public areas
new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require(`./public/vendor/vue-manifest.json`)})new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require(`./public/vendor/antd-manifest.json`)})new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require(`./public/vendor/echarts-manifest.json`})]}}Copy the code
Index.html configuration
Import repository JS files in index.html.
index.html
<script src="/vendor/vue.dll.js"></script>
<script src="/vendor/antd.dll.js"></script>
<script src="/vendor/echarts.dll.js"></script>
Copy the code
Note: To avoid errors when refreshing the page on a non-root path of the Vue route, use an absolute path.
The main description
-
Context (absolute path) The requested context in the manifest (or content property), where process.cwd() is used to return the current working directory.
-
Manifest is an object containing content and name, or a string — the path to load the JSON manifest at compile time.
Configure script commands
The plug-in configuration is complete.
Run script commands to generate dynamic repositories before packaging, usually only once over a long period of time, because these dependencies don’t change very often, and the resulting repositories are generally uploaded to the repository.
configuration
package.json
{..."scripts": {
"dll": "webpack --progress ./webpack.dll.config.js"}}Copy the code
Run the command
$ npm run dll
Copy the code
skills
Use add-asset-html-webpack-plugin to automatically import the repository
When you have enough dependencies to generate a large number of repository files; Or when you’re adding or deleting dependencies, or reprogramming your repository names, it’s not a good idea to introduce them in HTML one by one.
The add-asset-html-webpack-plugin can help you solve this problem.
Pay attention to
According to the official documentation of the plugin, after migrating to WebPack 4+, the plugin needs to be applied after the HtmlWebpackPlugin in order to register a hook, which was not required in previous WebPack versions.
configuration
vue.config.js
module.exports = {
configureWebpack: config= > {
plugins: [...new HtmlWebpackPlugin({
title: 'My Project'.template: 'public/index.html'.favicon: 'public/logo.png'
})
new AddAssetHtmlPlugin({
// DLL file location
filepath: path.resolve(__dirname, './public/vendor/*.js'),
// DLL reference path, please use absolute path!!
publicPath: '/vendor'.// DLL final output directory
outputPath: './vendor'}}})]Copy the code
SRC path generated by the publicPath script tag. If you use a Vue route, refresh the page in any non-root path. If you use a relative path, it will cause an error to join the route before the js file path of the repository. So you must use absolute paths here, remember! .
Filepath DLL file location, configure *.js to enable the plug-in to load all resource library js files in the directory.
Note: After using the HtmlWebpackPlugin, the page will be reconstructed according to the template, so you need to use the exposed variables supported by the plugin. The original BASE_URL variable will be invalid. Using htmlWebpackPlugin. Options. The title, and remove the favicon reference link tag.
index.html
<head>
<title><%= htmlWebpackPlugin.options.title %></title>
<! -- <link rel="icon" href="<%= BASE_URL %>favicon.ico"> -->
</head>
Copy the code
Optimizing the allocation of
DllReferencePlugin plugin configuration code duplication, optimization. In the webpack.dll.config.js file we can actually get all the names, that is, we can iterate over them.
vue.config.js
const DllConfig = require('./webpack.dll.config')
module.exports = {
configureWebpack: config= > {
let plugins = [
...
]
// Avoid recompiling dependencies in public areas
Object.keys(DllConfig.entry).forEach(key= >{
plugins.push(new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require(`./public/vendor/${key}-manifest.json`)}})))// Integrate plugins
config.plugins = [...config.plugins, ...plugins]
}
}
Copy the code
Pay attention to the problem
Environmental restrictions
Do not use add-asset-html-webpack-plugin in a development environment as this will affect hot loading in that environment (mainly because HtmlWebpackPlugin, its predecessor, updates all pages when it is hot updated). The specific reason may be webpack’s cache: After hot loading is triggered, Webpack does not re-read the configuration file. After refreshing the page, it cannot insert script tags into the HTML, causing the page to directly report an error.
Path to the script tag
When using the Vue Router: The publicPath in the AddAssetHtmlPlugin configuration must use an absolute path, or the script tag imported directly to the page must use an absolute path. Otherwise, the page will display an error when the non-root path is refreshed.
This has been illustrated and exemplified above.
Integrated configuration
An integrated reference configuration.
vue.config.js
const path = require('path')
const webpack = require('webpack')
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const DllConfig = require('./webpack.dll.config')
module.exports = {
...
configureWebpack: config= > {
let plugins = [
new HtmlWebpackPlugin({
title: 'My Project'.template: 'public/index.html'.favicon: 'public/logo.png'})]if (process.env.NODE_ENV === 'production') {
// Inject the generated DLL file into the generated HTML template
plugins.push(new AddAssetHtmlPlugin({
// DLL file location
filepath: path.resolve(__dirname, './public/vendor/*.js'),
// DLL reference path
publicPath: '/vendor'.// DLL final output directory
outputPath: './vendor'
}))
// Avoid recompiling dependencies in public areas
Object.keys(DllConfig.entry).forEach(key= >{
plugins.push(new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require(`./public/vendor/${key}-manifest.json`)})}}))// Integrate plugins
config.plugins = [...config.plugins, ...plugins]
}
}
Copy the code
webpack.dll.config.js
// Define common objects
const path = require('path')
const webpack = require('webpack')
const CleanWebpackPlugin = require('clean-webpack-plugin')
// Directory for storing DLL files
const dllPath = 'public/vendor'
module.exports = {
// The library file to extract
entry: {
vue: ["vue"."vue-router"."vuex".'axios'].antd: ["ant-design-vue"].echarts: ["echarts"],},output: {
path: path.join(__dirname, dllPath),
filename: '[name].dll.js'.// Global variable name exposed in vendor.dll.js
// Keep the same name as webpack.dllPlugin
library: '[name]_[hash]'
},
plugins: [
// Clear the previous DLL file
new CleanWebpackPlugin(['*. *'] and {root: path.join(__dirname, dllPath)
}),
// Define the plug-in
new webpack.DllPlugin({
path: path.join(__dirname, dllPath, '[name]-manifest.json'),
// keep the same name as output.library
name: '[name]_[hash]'.context: process.cwd()
})
]
}
Copy the code