Webpack 插件扫盲系列(二)webpack.DllPlugin 和 webpack.DllReferencePlugin

一、概念

DLLPluginDLLReferencePlugin用某种方法实现了拆分 bundles,同时还大大提升了构建的速度,将包含大量复用模块且不会频繁更新的库进行编译,只需要编译一次,编译完成后存在指定的文件中。在之后的构建过程中不会再对这些模块进行编译,而是直接使用 DllReferencePlugin 来引用动态链接库的代码。一般会对常用的第三方模块使用这种方式,例如 react、react-dom、lodash 等。只要这些模块不升级更新,这些动态链接库就不需要重新编译。故我们需要创建一个单独的webpack打包任务,单独先打包那些些复用模块且不会频繁更新的库,再在我们的打包流程中引用打包的dll.

二、创建webpack.dll.conf.js 单独打包dll

该打包只输出打包后的 _dll_xxx[hash].jsxxx.manifest.json

const webpack = require("webpack")
const path = require('path')
const CleanWebpaclPlugin = require('clean-webpack-plugin');
const resolve = (dir) => path.join(__dirname, '..', dir);

module.exports = {
  entry: {
    # 将 react、lodash等模块作为入口编译成动态链接库
    vendor: ['react', 'react-dom', 'react-router-dom', 'lodash']
  },
  output: {
    # 指定生成文件所在目录文件夹,
    # 将它们存放在了 src 文件夹下
    path: resolve('public'),
    # 指定文件名
    library: '_dll_[name]',
    # 存放动态链接库的全局变量名称,例如对应 lodash 来说就是 lodash_dll_lib
    # 这个名称需要与 DllPlugin 插件中的 name 属性值对应起来
    filename: 'dll/_dll_[name].[hash].js'
  },
  plugins: [
    new CleanWebpaclPlugin(['dll'], {
        root: resolve('public')
    }),
    new webpack.DllPlugin({
      name: '_dll_[name]',
    # 和output.library中一致,值就是输出的manifest.json中的 name值
      path: path.join(__dirname, '../public/dll', '[name].manifest.json')
    })
  ]
}

三、通过webpack.DllReferencePlugin在主打包环境中引用dll库

const path = require('path');
const webpack = require('webpack');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const CleanWebpaclPlugin = require('clean-webpack-plugin');
const resolve = (dir) => path.join(__dirname, '..', dir);

module.exports = {
    entry: './src/index.js',
    output: {
        path: resolve('dist'),
        filename: 'js/[name].[hash].js',
        library: '_dll_[name]'
    },
    plugins: [
        # 需添加root 否则无法删除,exclude未生效
        new CleanWebpackPlugin(['dist'], {
          root: path.join(__dirname, '..')
        }),
        new HTMLWebpackPlugin({
            title: 'Webpak DllPlugin 的使用',
            template: resolve('index.html'),
            filename: 'index.html'
        }),
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify('production')
        }),
        # 告诉 Webpack 使用动态链接库
        new webpack.DllReferencePlugin({
            // 描述 lodash 动态链接库的文件内容
            manifest: require(../public/dll/vendor.manifest')
        })
    ]
}

四、查看效果

例如我将crypto.js 单独打包成dll.

 entry: {
        vendor: [
            'crypto-js',
            ],
    }

生成的mainfest.jsn如下

//--此处省略
"../node_modules/crypto-js/sha1.js": {
       "id": 6,
       "buildMeta": {
           "providedExports": true
       }
   },
   "../node_modules/crypto-js/hmac.js": {
       "id": 7,
       "buildMeta": {
           "providedExports": true
       }
   },
   "../node_modules/crypto-js/sha256.js": {
       "id": 8,
       "buildMeta": {
           "providedExports": true
       }
   },
   "../node_modules/crypto-js/sha512.js": {
       "id": 9,
       "buildMeta": {
           "providedExports": true
       }
   },
   "../node_modules/crypto-js/index.js": {
       "id": 11,
       "buildMeta": {
           "providedExports": true
       }
   }
   //--此处省略

当我在主包内直接引用crypto-js

import getAxios from "../../../util/axiosDefault";
import log from "../../../util/log";

var CryptoJS = require("crypto-js");

export const getCry = (param)=>{
	return CryptoJS.SHA256(param).toString();
}

打包后的代码如下:

/***/ "../node_modules/crypto-js/index.js":
/*!**************************************************************************************!*\
  !*** delegated ../node_modules/crypto-js/index.js from dll-reference vendor_library ***!
  \**************************************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

module.exports = (__webpack_require__(/*! dll-reference vendor_library */ "dll-reference vendor_library"))(11);

/***/ }),

注意后面的(11) 这个序号就是包的key,看下mainfest.json中对应的是不是11。webpack会通过这个寻找dll中的相应模块。

当我换一种方式引用crypto-js,直接引用SHA256的情景:

import getAxios from "../../../util/axiosDefault";
import log from "../../../util/log";

var SHA256= require("crypto-js/sha256");

export const getCry = (param)=>{
	return SHA256(param).toString();
}

大家猜一下打包后的代码是什么?没错,只是修改了模块引用的id,从11变成了8

/***/ "../node_modules/crypto-js/index.js":
/*!**************************************************************************************!*\
  !*** delegated ../node_modules/crypto-js/index.js from dll-reference vendor_library ***!
  \**************************************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

module.exports = (__webpack_require__(/*! dll-reference vendor_library */ "dll-reference vendor_library"))(8);

/***/ }),

你可能感兴趣的:(webpack,前端技术)