React系列---Webpack環境搭建(三)打包性能優化

React系列---Webpack環境搭建(一)手動搭建
React系列---Webpack環境搭建(二)不一樣環境不一樣配置
React系列---Webpack環境搭建(三)打包性能優化javascript


實際項目,動輒上千個模塊,打包花1分鐘以上是很常見的。咱們構建的時候,每每但願本身的代碼和第三方庫(vendors)能夠分開打包,由於不涉及到升級第三方庫時,就不必每次浪費打包時間在這上面。html

Dll(動態連接庫)是Webpack後面加入的功能,Dll這個概念應該是借鑑了Windows系統的dll。一個dll包,就是一個純粹的依賴庫,它自己不能運行,是用來給你的app引用的。java

打包dll的時候,Webpack會將全部包含的庫作一個索引,寫在一個manifest文件中,而引用dll的代碼(dll user)在打包的時候,只須要讀取這個manifest文件,就能夠了。react

這麼一來有幾個好處:webpack

  1. Dll打包之後是獨立存在的,只要其包含的庫沒有增減、升級,hash也不會變化,所以線上的dll代碼不須要隨着版本發佈頻繁更新。
  2. App部分代碼修改後,只須要編譯app部分的代碼,dll部分,只要包含的庫沒有增減、升級,就不須要從新打包。這樣也大大提升了每次編譯的速度。
  3. 假設你有多個項目,使用了相同的一些依賴庫,它們就能夠共用一個dll。

如何使用呢?git

首先要先創建一個dll的配置文件,entry只包含第三方庫。
webpack.dll.config.js:github

const path = require('path')
const webpack = require('webpack')

const ROOT_PATH = path.resolve(__dirname);

const vendors = [
  'react',
  'react-dom',
  'react-redux',
  'react-router',
  'react-router-redux',
  'redux',
  'redux-actions',
  'antd',
  'moment',
];

module.exports = {
  entry: {
    vendor: vendors
  },
  output: {
    path: path.resolve(__dirname, 'lib'),
    filename: '[name].dll.js',
    library: '[name]_lib',
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.resolve(ROOT_PATH, 'lib', 'manifest.json'),
      name: '[name]_lib',
      context: ROOT_PATH,
    }),
  ],
}

webpack.DllPlugin的選項中,path是manifest文件的輸出路徑;name是dll暴露的對象名,要跟output.library保持一致;context是解析包路徑的上下文,這個要跟下面要配置的DllReferencePlugin保持一致。web

修改package.json,增長dll命令:npm

"scripts": {
    "dll": "rimraf ./lib && webpack --config webpack.dll.config.js",
    "start": "webpack-dev-server --hot --progress --config webpack.dev.config.js",
    "build:dev": "rimraf build && webpack --progress --config webpack.dev.config.js",
    "build:test": "rimraf build && webpack --progress --config webpack.test.config.js",
    "build:prod": "rimraf build && webpack --progress --config webpack.prod.config.js"
  },

執行命令,生成第三方依賴dll庫:json

npm run dll

能夠看到lib目錄下生成了兩個文件:

clipboard.png

修改webpack.base.config.js配置,增長DllReferencePlugin插件配置:

plugins: [
    new webpack.DllReferencePlugin({
        manifest: require(path.resolve(ROOT_PATH, 'lib', 'manifest.json')),
        context: ROOT_PATH,
    })
]

這麼一來,已作成dll庫的那部分模塊,webpack將不會重複打包。
DllReferencePlugin的選項中,context須要跟以前保持一致,這個用來指導Webpack匹配manifest中庫的路徑;manifest用來引入剛纔輸出的manifest文件。

最後修改一下模板index.html,增長引用vendor.dll.js文件:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
  <div id="root"></div>
  <script type="text/javascript" src="../lib/vendor.dll.js"></script>
</body>
</html>

給入口文件再加點依賴模塊,方便打包觀察:

import React from 'react';
import ReactDOM from 'react-dom';
import { DatePicker } from 'antd';
import moment from 'moment';
import 'moment/locale/zh-cn';

moment.locale('zh-cn');

function Index() {
    return (
      <div className="container">
        <h1>Antd DatePicker!</h1>
        <DatePicker defaultValue={moment('2015-01-01', 'YYYY-MM-DD')} />
      </div>
    );
}

ReactDOM.render(<Index />, document.getElementById('root'));

export default Index;

運行打包:

npm run build:dev

clipboard.png

能夠看到,入口文件裏依賴的react,moment模塊,直接引用了dll。

對比一下不作分離的狀況下打包的結果:
clipboard.png

速度快了,文件也小了。平時開發的時候,修改代碼後從新編譯的速度會大大減小,節省時間。

代碼:https://github.com/zhutx/reac...


React系列---Webpack環境搭建(一)手動搭建
React系列---Webpack環境搭建(二)不一樣環境不一樣配置React系列---Webpack環境搭建(三)打包性能優化

相關文章
相關標籤/搜索