webpack4之DllPlugin配置

使用 DllPlugin 插件先提前打包一些不经常变化的第三方库,然后在后面项目打包的时候直接引用它们,而不需要重新打包这些库,这样可以有效的提升项目打包速度。

目录
  1. 基础配置
  2. 多个入口配置
  3. 自动引入

使用 DllPlugin 插件先提前打包一些不经常变化的第三方库,然后在后面项目打包的时候直接引用它们,而不需要重新打包这些库,这样可以有效的提升项目打包速度。

基础配置#

首先,需要新建一个 Webpack 配置文件webpack.dll.config.js,配置文件的代码如下

const path = require("path");
const webpack = require("webpack");
 
module.exports = {
  mode: "production",
  entry: {
    vendors: ["react", "react-dom"],
  },
  output: {
    path: path.resolve(__dirname, "dll"),
    filename: "[name].dll.js",
    library: "[name]", // 设置库的名称
  },
  plugins: [
    // 使用 DllPlugin 插件
    new webpack.DllPlugin({
      name: "[name]",
      path: path.resolve(__dirname, "dll/[name].manifest.json"), // 打包后存储路径
    }),
  ],
};

这里把reactreact-dom这两个库先提前打包,输出一个vendors的文件。在新的配置文件中需要引入webpack自带``DllPlugin`插件,这样才能按照配置生成新的所需要的打包文件。

package.json新增一个打包命令

"scripts": {
  "build:dll": "webpack --config webpack.dll.config.js"
}

然后进行编译打包

yarn build:dll

发现在根目录下面新增了dll文件夹,里面是刚才打包生成的两个文件

  • vendors.dll.js打包后的文件
  • vendors.manifest.json打包后的文件映射清单

现在已经提前打包好了两个第三方库,然后需要修改原来 Webpack 的配置文件webpack.config.js

// ...
const webpack = require("webpack");
const AddAssetHtmlWebpackPlugin = require("add-asset-html-webpack-plugin");
 
module.exports = {
  // ...
  plugins: [
    // ...
    new AddAssetHtmlWebpackPlugin({
      filepath: path.resolve(__dirname, "dll/vendors.dll.js"),
    }),
    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, "dll/vendors.manifest.json"),
    }),
  ],
};

这里还是使用了DllReferencePlugin插件,但是配置不一样,这里配置manifest选项引入之前打包好的文件的映射清单,然后再借助一个第三方库add-asset-html-webpack-plugin把打包好的文件引入到现在的 HTML 文件中。

修改好原来的配置文件后,重新进行打包编译。

yarn build

文件打包成功。我们可以通过注释掉DllReferencePlugin插件的代码,进行编译打包,多打包几次。然后取消注释,也进行编译打包,也多打包几次。然后比较这两种配置之间的打包时间,就会发现使用DllReferencePlugin插件后编译打包的时间明显更少。因为使用DllReferencePlugin插件后就不需要再重新去打包reactreact-dom这两个库了,而是直接引用原来已经打包好的文件。

现在启动开发模式测试一下。

yarn dev

发现编译也是成功的。

多个入口配置#

目前项目只是提前打包了两个第三方库,打包后生成的文件也只有两个。但是随着项目越来越大,使用的第三方库会越来越多,到时候需要提前打包的库也会越来越多。这时,也不可能把所有的库都打包在一起,可以把它们分开打包,这时候需要使用多个入口来进行编译打包。

比如我们还引用了lodash库,修改webpack.dll.config.js配置文件,增加一个新的入口

module.exports = {
  entry: {
    vendors: ["lodash"],
    react: ["react", "react-dom"],
  },
  // ...
};

然后重新进行编译打包,发现在根目录下面的dll文件夹下,里面变成了四个文件,比原来的数目多了两个,这是因为增加了一个入口,所以打包后多出了两个文件。

这样就需要再次修改webpack.config.js配置文件,把上面打包多出来的两个文件也要引入进来。

module.exports = {
  // ...
  plugins: [
    // ...
    new AddAssetHtmlWebpackPlugin({
      filepath: path.resolve(__dirname, "dll/vendors.dll.js"),
    }),
    new AddAssetHtmlWebpackPlugin({
      filepath: path.resolve(__dirname, "dll/react.dll.js"),
    }),
    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, "dll/vendors.manifest.json"),
    }),
    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, "dll/react.manifest.json"),
    }),
  ],
};

重新进行编译打包,打包成功。使用开发者模式测试代码,编译也是成功的。

自动引入#

上面使用dllPlugin配置了两个入口,打包出来四个文件。如果项目很大的话,可能需要提前打包很多的库。入口也会变的更多,打包出来的文件也会更多,那么在原来的webpack.config.js文件也需要引入更多的文件。而且我们不可能每次打包后都需要手动引入进来,这样会非常麻烦,这时需要编写代码自动引入提前打包好的库。

我们可以使用 Node.js 的 fs 模块读取dll文件夹的所有文件信息,然后遍历这样文件,通过正则表达式筛选出文件类型,再通过插件引入相应的文件,这样就不怕引入的文件很多,因为可以自动引入文件了。

修改webpack.config.js配置文件

// ...
const fs = require("fs");
 
// 先把其他的插件提取出来
const plugins = [
  new HtmlWebpackPlugin({
    template: path.resolve(__dirname, "index.html"),
    filename: "index.html",
  }),
  new webpack.HotModuleReplacementPlugin(),
];
 
// 读取打包后的所有文件名
const files = fs.readdirSync(path.resolve(__dirname, "dll"));
 
// 遍历文件名,通过正则匹配使用插件引入对应的文件
files.forEach((file) => {
  if (/.*\.dll.js/.test(file)) {
    plugins.push(
      new AddAssetHtmlWebpackPlugin({
        filepath: path.resolve(__dirname, "dll", file),
      })
    );
  }
  if (/.*\.manifest.json/.test(file)) {
    plugins.push(
      new webpack.DllReferencePlugin({
        manifest: path.resolve(__dirname, "dll", "vendors.manifest.json"),
      })
    );
  }
});
 
module.exports = {
  // ...
  plugins,
};

修改配置的步骤如下

  1. 通用的插件先提取出来,存储在plugins数组中。
  2. 通过fs.readdirSync读取dll文件夹中所有的文件名信息,存储到files数组中。
  3. 遍历文件名数组files,通过正则表达式匹配文件名,再使用插件引入匹配的文件,再把插件放入到plugins数组中。
  4. 最后把plugins数组赋值给配置文件的plugins字段中。

重新进行编译打包,打包成功。使用开发者模式测试代码,编译也是成功的。说明自动引入的方法是有效的,以后再也不用担心提前打包的文件多的问题。