webpack速度提升之DllPlugin和DllReferencePlugin

3,163 阅读3分钟

一、webpack.DllPlugin和webpack.DllReferencePlugin 是干嘛的?

说白了,就是把项目里面依赖的第三方库,比如react, vue, echarts, moment 这些不会经常变动的包,提前打包好。

然后在webpack构建中,引入这些提前打包好的bundle的依赖(mainfest.json),这样在项目构建时候,就不用每次都重复编译这些不经常变动的库,从而提高webpack的打包速度

二、使用方法,从0开始一步步来

1、新建一个工程,目录结构如下

2、public/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
      <meta charset="UTF-8">
      <title>DllPlugin和DllReferencePlugin</title>
  </head>
  <body>
        <div id="app"></div>
  </body>
</html>

3、src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from '../App';

ReactDOM.render(
  <App />,
  document.getElementById('app'),
);

这里不是重点,只是用react项目做例子,不管是vue,react,等等,还是其他的,都是阔以

3、src/App.js

import React from 'react';
import moment from 'moment';

const App = () => (
  <div>
    我是React项目
    <h1>react,还是vue项目,都无妨,这里不是重点</h1>
    <h1> {moment().format('YYYY-MM-DD hh:mm:ss')}</h1>
  </div>
);

export default App;

三、接下来,我们看下build里的东西 (用的是webpack 4.44.1)

安装包

npm i webpack webpack-cli html-webpack-plugin path clean-webpack-plugin babel-loader -D

npm i @babel/core @babel/preset-env @babel/preset-react -D

npm i react react-dom moment -S

1、首先看下咋门不用DllPlugin和DllReferencePlugin的时候的构建速度

build/webpack.base.conf.js

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
        mode: "production",
        entry: {
            app: path.resolve(__dirname, '../src/index.js'),
        },
        output: {
            filename: "js/bundle.js",
            path: path.resolve(__dirname, '../dist')
        },
        optimization: {
            minimize: true,
        },
        module: {
            rules: [
                {
                    test: /\.(js|jsx)?$/,
                    exclude: /(node_modules|bower_components)/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                          presets: ['@babel/preset-env', '@babel/preset-react']
                        }
                    }
                },
            ]
        },
        plugins: [
            new CleanWebpackPlugin(),
            new HtmlWebpackPlugin({
                template: 'public/index.html',
                inject: 'body'
            }),
        ],
};

2、package.json的scripts里面添加

 "build": "webpack --config build/webpack.base.conf.js",

3、运行 npm run build 的结果

我们看到 bundle.js 非常大,速度6246秒多

4、现在加上,DllPlugin和DllReferencePlugin

  1. 在build/webpack.dll.config.js里面加上
new webpack.DllPlugin({
            path: path.resolve(__dirname, '../static/[name]-manifest.json'),
            name: '[name]_lib',
  })
  
  1. build/webpack.dll.config.js全文件

const webpack = require('webpack');
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    mode: "production",
    entry: {
        //把第三方库集中打包
        vendor: ['react', 'react-dom', 'moment']
    },
    output: {
        filename: '[name].dll.js',
        path: path.resolve(__dirname, '../static'),
        library: '[name]_lib', 
    },
    plugins: [
        new CleanWebpackPlugin(),
        new webpack.DllPlugin({
            path: path.resolve(__dirname, '../static/[name]-manifest.json'),
            name: '[name]_lib', //这个name 和 library 对应
        })
    ]
};


  1. 最后在 package.json里面加上
"build:dll": "webpack --config build/webpack.dll.config.js",
  1. 然后运行 npm run build:dll, 此时在根目录下面自动创建了一个static文件夹 vendor.dll.js 是第第三方库的打包后的文件,vendor-manifest.json 是对第三方库的一个引用,(稍后再webpack.base.cong.js里面用到),这样我们就把第三方库提前打包好了

  2. 接下再webpack.base.cong.js里面添加

 new webpack.DllReferencePlugin({
              manifest: require(path.join(__dirname, '../static/vendor-manifest.json'))
}),
  1. 然后再运行 npm run build 重新打包
此时`bundle.js`变成了`1.47kib`了和之前对比小了非常非常非常多。
而且速度也变成了 2200ms (之前是6246) 着实提升不少 
那么这个时候我们看下`dist/index.html`还是没有自动引入提前打包号的`vendor.dll.js`
  1. 有两个方法引入
1:再public/index.html里面手动把static/vendor.dll.js引入到body后面

2:利用html-webpack-plugin 来引入
  1. 我们来用html-webpack-plugin自动引入
// webpack.base.conf.js里面添加
 new HtmlWebpackPlugin({
                template: 'public/index.html',
                inject: 'body',
                dllName: ['static/vendor.dll.js']
}),
  1. 修改public/index.html
<% if (htmlWebpackPlugin.options.dllName) { %>
       <script src="<%=htmlWebpackPlugin.options.dllName%>"></script>
<% } %>
这里是ejs的语法,动态加载 HtmlWebpackPlugin 里面的 dllName
  1. 再运行 npm run build 此时看到dist/html里面打包后的文件已经引入了 static/vendor.dll.js

  2. 利用 copy-webpack-plugin 把static里面的文件移动到 dist 里面来

new CopyWebpackPlugin({
        patterns: [
           { from: path.join(__dirname, '../static'),
             to: path.join(__dirname, '../dist/static')},
       ],
}),
  1. 再运行 npm run build,完成

来到dist目录下 运行 anywhere

一、结语

感谢各位老铁,点赞加关注, demo地址: github.com/iwen-pengh/…