【webpack】DLL plugin原理分析

DLL plugin打包步骤

.dll为后缀的文件称为动态链接库,在一个动态链接库中可以包含给其他模块调用的函数和数据
把基础模块独立打包出来放到单独的动态链接库里
当需要导入的模块在动态链接库的时候,模块不能再次打包,而且从动态链接库里面获取

DllPlugin插件:用于打包一个个动态链接库
DllReferencePlugin:在配置文件中引入DllPlugin插件打包好的动态链接库

1、定义配置文件和命令

  "build:dll": "webpack --config build/webpack.dll.config.js --mode=development"

webpack.dll.config.js配置处理

/*
 * @description:
 * @author: steve.deng
 * @Date: 2020-09-25 12:53:31
 * @LastEditors: steve.deng
 * @LastEditTime: 2020-09-25 13:24:27
 */
const path = require("path");
// const DllPlugin = require("webpack/lib/DllPlugin");
const webpack = require('webpack')
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
module.exports = {
     
  entry: {
     
    vendor: ['vue/dist/vue.esm.js', 'element-ui/lib/element-ui.common.js', 'wangeditor', 'mathjs', 'echarts', 'html2canvas', 'vue-router', 'vuex']
  },
  output: {
     
    path: path.resolve(__dirname, "../static/js"),
    filename: "[name].dll.js", //vendor.dll.js
    library: "_dll_[name]_library",//库的名字叫 _dll_[name]_library 决定了 vendor.dll.js里面库的名字
    // vendor.dll.js中暴露出的全局变量名。
    // 主要是给DllPlugin中的name使用,
    // 故这里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
  },
  plugins: [
    new webpack.DllPlugin({
     
      // context: path.join(__dirname, '../'),
      name: "_dll_[name]_library", // 决定了.manifest里面的name名字 和 上面library对应
      path: path.join(__dirname, '../static/js', '[name]-manifest.json'),
    }),
    // new ParallelUglifyPlugin({
     
    //   cacheDir: '.cache/',
    //   uglifyJS: {
     
    //     output: {
     
    //       comments: false
    //     },
    //     compress: {
     
    //       warnings: false
    //     }
    //   }
    // })
  ],
};

// 一般放在生产配置就好了 开发环境建议不要用 比如vue库的一些错误提示会打包成时被省略了 ,会开发环境不友好 ,
webpack.prod.conf.js

plugins: [
    // 引用插件
    new webpack.DllReferencePlugin({
     
      // 这里的上下文要与dllplugin保持一致
      // context: path.join(__dirname, '../'),
      manifest: require('../static/js/vendor-manifest.json')
    })
]

html引入打包好的包

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <link rel="shortcut icon" href="static/images/favicon.ico">
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script>
 
    </script>
    <script type="text/javascript" src="/static/js/vendor.dll.js"></script>
  </body>
</html>

原理

xx.manifest.json
name指的是对应的dll库名字
描述了哪些模块被打进来dll了, 用模块名当id标识出来 大概是一个模块清单
【webpack】DLL plugin原理分析_第1张图片
xxx.dll.js 就是模块的源码了
xxx.dll.js 是各个模块的源码集合 通过key(模块id)–> value查询出来
【webpack】DLL plugin原理分析_第2张图片
上面文件 其实就是一个 全局变量 var _dll_react = xxxx;
【webpack】DLL plugin原理分析_第3张图片
那么webpack如何查找打包好的模块呢?而不需要重复打包

1、比如index.js引入了 react

import React from 'react';
//./node_modules/[email protected]@react/index.js

console.log(React);

2、他会去mainfest.json找模块id 其实就是react关键字拼接版本号 + index.js组成id去寻找模块
即 ‘./node_modules/’+’[email protected]@react’+ ‘/index.js’ 组成的id

3、找到有模块的话,就不再去打包了
打包出来的bundle.js直接会引入上面打包好的dll库,dll库会暴露一个全局变量_dll_react

  • bundle.js里面 会有一个定义好的key “dll-reference _dll_react” 对应 打包出来的全局变量,对应是全部的打包出来的第三方模块
/***/ (function(module, __webpack_exports__, __webpack_require__) {
     

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/[email protected]@react/index.js");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);

console.log(react__WEBPACK_IMPORTED_MODULE_0___default.a);

/***/ }),

/***/ "dll-reference _dll_react":
/*!*****************************!*\
  !*** external "_dll_react" ***!
  \*****************************/
/*! no static exports found */
/***/ (function(module, exports) {
     

module.exports = _dll_react;

/***/ })

/******/ });
  • index.js实际引入了react
    bundle.js里面就有
    “./src/index.js”: webpack_require(/*! react */ “./node_modules/[email protected]@react/index.js”);

/***/ "./src/index.js":
/*!**********************!*\
  !*** ./src/index.js ***!
  \**********************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
     

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/[email protected]@react/index.js");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);

console.log(react__WEBPACK_IMPORTED_MODULE_0___default.a);

/***/ }),
  • webpack_require(/*! react */ “./node_modules/[email protected]@react/index.js”); 其实就是指向刚才的全局变量

“./node_modules/[email protected]@react/index.js"就是"dll-reference _dll_react"里面的某个key读取
所以可以通过(webpack_require(/*! dll-reference _dll_react */ “dll-reference _dll_react”))(”./node_modules/[email protected]@react/index.js")就能读取了react代码了


/***/ "./node_modules/[email protected]@react/index.js":
/*!********************************************************************************************!*\
  !*** delegated ./node_modules/[email protected]@react/index.js from dll-reference _dll_react ***!
  \********************************************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
     

module.exports = (__webpack_require__(/*! dll-reference _dll_react */ "dll-reference _dll_react"))("./node_modules/[email protected]@react/index.js");

/***/ }),

大致就是这个流程了

你可能感兴趣的:(webpack)