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