項目打包優化之DllPlugin

dll-plugin

DllPlugin 插件配置實踐node

做用

DLLPlugin 和 DLLReferencePlugin 用某種方法實現了拆分 bundles,同時還大大提高了構建的速度。jquery

  • DllPlugin: 將第三方依賴與項目分離,將全部第三方庫代碼單獨打成dll文件,項目每次打包只須要打包本項目代碼。
  • DllReferencePlugin: 找到項目中所用到的第三方依賴在dll中的位置。

用法

工程目錄webpack

### 目錄結構以下:
  dll-plugin                                       # 工程名
  |   |--- dist                               # 打包後生成的目錄文件             
  |   |--- node_modules                       # 全部的依賴包
  |   |--- src                                # 存放全部js文件
  |   | |-- pageOne.js  
  |   | |-- pageTwo.js                        # js入口文件
  |   |--- webpack.config.js                  # webpack配置文件
  |   |--- webpack.dll.config.js              # 打包第三方依賴的庫文件
  |   |--- README.md
  |   |--- package.json
複製代碼

首先咱們須要在項目下建立一個單獨的打包dll文件的配置文件webpack.dll.config.jsweb

const path = require('path');
const webpack = require('webpack');
const library = '[name]_dll_lib';

module.exports = {
	mode: 'development',
  // 入口, 接收多個參數做爲多個入口
  entry: {
    // dll文件中包含的第三方庫列表
    jquery: ['jquery'],
    echarts: ['echarts']
  },
  output: {
    // 文件名稱
    filename: 'dll/[name].dll.js',
    // 文件輸出目錄
    path: path.resolve(__dirname, 'dist'),
    // 存放dll文件的全局變量名稱,須要注意命名衝突
    library: library
  },
  plugins: [
    new webpack.DllPlugin({
      // manifest文件中的name屬性值, 需與output.library保持一致
      name: library,
      // mainfest文件輸出路徑和文件名稱
      path: path.join(__dirname, 'dist', 'dll/[name].manifest.json')
    })
  ]
}
複製代碼

接下來須要在webpack.config中使用的manifestnpm

module.exports = {

  /***** other options ******/

  plugins: [
    // 告訴webpack使用了哪些第三方庫代碼
    new DllReferencePlugin({
      // manifest文件中請求的上下文,
      context: __dirname,
      // jquery 映射到json文件上去
      manifest: require('./dist/jquery.manifest.json')
    }),
    new DllReferencePlugin({
      // echarts 映射到json文件上去
      manifest: require('./dist/echarts.manifest.json')
    })
  ]
}
複製代碼

package.json 中添加打包命令json

"scripts": {
  "build:dll": "webpack --config webpack.dll.config.js",
},
複製代碼

運行npm run build:dll, 運行完成以後,會在dist/dll目錄下生成 echarts.dll.js, echarts.manifest.json,jquery.dll.js, jquery.manifest.json 文件echarts

dll文件

在src/pageOne.js入口文件中引入jquery和echarts庫, src/pageTwo.js文件中不引入任何依賴ide

const jquery = require('jquery');
const echarts = require('echarts');

console.log("Hello World from pageOne main file!");
複製代碼

執行打包命令 npm run build 函數

使用dll打包時間
使用dll打包文件大小

發現打包的時間是668ms, pageOne和pageTwo打包出來的大小僅相差了3kb, 顯然第三方庫代碼沒有打包到項目文件裏。再來對比一下使用dll和不使用dll的狀況優化

不使用dll打包時間
不適用dll打包文件大小

打包時間變成了1781ms, 增長了近兩倍, 打包大小變爲3683KB, 將jquery和echarts第三方庫代碼打包進了pageOne中。

結論

使用DllPlugin分離bundle,構建速度和工程文件大小優化明顯。

原理

瞭解dll-plugin的做用和用法後,再來看看它是怎麼實現的。

先看一下打包生成的dll文件, echarts.dll.js:

var echarts_dll_lib = (function(modules) {
  // ... 此處省略 webpackBootstrap 函數代碼
}({
  "./node_modules/echarts/index.js": (function(module, exports, __webpack_require__) {
    // ID爲./node_modules/echarts/index.js模塊對應的代碼
  }),
  "./node_modules/echarts/lib/CoordinateSystem.js": (function(module, exports, __webpack_require__) {
    // ID爲./node_modules/echarts/lib/CoordinateSystem.js模塊對應的代碼
  }),
  // ......
}));
複製代碼

DllPlugin 將echarts依賴導出成了一個函數,並將echarts_dll_lib掛載到window全局對象中, 能夠看到dll爲echarts中的各個模塊都分配了一個Id。

再看echarts.manifest.json:

{
  "name":"echarts_dll_lib",
  "content": {
    "./node_modules/echarts/lib/util/animation.js": {
      "id": "./node_modules/echarts/lib/util/animation.js",
      "buildMeta":{"providedExports":true}
    },
    // .....
    "./node_modules/echarts/index.js": {
      "id":"./node_modules/echarts/index.js",
      "buildMeta": {"providedExports":true}
    },
    // ......
  }
}
複製代碼

echarts.manifest.json 文件能夠清楚的看到與其對應的dll.js文件中包含了哪些模塊,以及每一個模塊的路徑和ID。

經過manifest尋找到依賴

在webpackConfig中配置DllReferencePlugin引入manifest, 當項目中引入echarts模塊時,會經過路徑匹配到manifest中的對應模塊id, 再經過模塊id和name屬性, 找到掛載再window上的對應的模塊代碼。

相關文章
相關標籤/搜索