Webpack DLL 配置教程

原理

DLL文件又稱爲動態連接庫文件,它一般做爲應用程序可執行代碼的一部分,供應用程序在運行時進行調用。html

在Webpack中,內置的DllPlugin與DllReferencePlugin插件能夠經過使用DLL來大幅提升構建性能,如下是DLL機制流程圖:
clipboard.pngnode

初始化項目

爲了便於實驗,咱們經過使用create-react-app建立項目並eject出webpack配置:react

npx create-react-app react-dll-demo
cd react-dll-demo && npm run eject

因爲默認配置隱藏了編譯信息,打開webpackDevServer.config.js,將quiet: true改成false,再啓動一下項目,找出咱們須要的信息:webpack

Version: webpack 4.28.3
Time: 6985ms
Built at: 2019-02-21 10:46:42
                         Asset       Size        Chunks             Chunk Names
           asset-manifest.json  232 bytes                [emitted]
                    index.html   1.65 KiB                [emitted]
          static/js/0.chunk.js   4.21 MiB             0  [emitted]
           static/js/bundle.js   30.9 KiB  runtime~main  [emitted]  runtime~main
       static/js/main.chunk.js   47.4 KiB          main  [emitted]  main
static/media/logo.5d5d9eef.svg   2.61 KiB                [emitted]

DLLPlugin

首先在package.json的scripts字段添加一條腳本:git

{
  "build:dll": "webpack --config config/webpack.dll.config.js --mode production"
}

而後建立配置文件:github

// config/webpack.dll.config.js

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

module.exports = {
  entry: {
    react: ['react', 'react-dom']
  },
  output: {
    filename: '[name].dll.js',
    path: path.join(__dirname, '../public/dll'),
    libraryTarget: 'var',
    library: '_dll_[name]_[hash]'
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, '../public/dll', '[name].manifest.json'),
      name: '_dll_[name]_[hash]'
    })
  ]
};

執行npm run build:dll,CLI應該會自動提示你安裝webpack-cli,運行完成後能夠看到如下文件:web

public/dll
├── react.dll.js
└── react.manifest.json

DLLReferencePlugin

打開config/webpack.config.js,在根對象plugins字段中寫入該插件:npm

{
  plugins: [
    // ...
    new webpack.DllReferencePlugin({
        manifest: require(path.join(
        __dirname,
        '../public/dll/react.manifest.json'
        ))
    }),
  ]
}

最後一個步驟,在index.html咱們先手動引入dll依賴:json

...
    <div id="root"></div>
    <script src="/dll/react.dll.js"></script>
    ...

此時從新運行程序,等待項目正常運行,再檢查一下編譯信息:緩存

Version: webpack 4.28.3
Time: 4883ms
Built at: 2019-02-21 11:19:11
                         Asset       Size        Chunks             Chunk Names
           asset-manifest.json  232 bytes                [emitted]
                    index.html   1.69 KiB                [emitted]
          static/js/0.chunk.js   1.82 MiB             0  [emitted]
           static/js/bundle.js   30.9 KiB  runtime~main  [emitted]  runtime~main
       static/js/main.chunk.js   52.1 KiB          main  [emitted]  main
static/media/logo.5d5d9eef.svg   2.61 KiB                [emitted]

很顯然的看到,在development模式下,構建時間下降了2s,打包大小下降了2.4M,相信將DLL運用到項目工程中,你能收穫到更多的驚喜。

優化

以上程序只是爲了快速入手與demo搭建,須要優化的地方還有不少,在此簡單的列舉幾點,供你們參考。

自動注入編譯文件到HTML

經過安裝html-webpack-include-assets-plugin插件,能夠自動將相應文件注入到index.html中,就能夠避免手動進行更改了:

// config/webpack.config.js
const HtmlIncludeAssetsPlugin = require('html-webpack-include-assets-plugin');
// ...
{
  plugins: [
    new HtmlIncludeAssetsPlugin({
      assets: ['dll/react.dll.js'],
      append: false // 在其餘資源前添加
    }),
  ]
}

DLL的緩存問題與自動加載

咱們一般不會對html文件作緩存,每次發版本時採用增量發佈,只要html的依賴文件名變了,則會從新去解析靜態資源列表。除此以外,還須要提供一個函數,自動去加載文件夾內的多入口dll文件,如下爲核心代碼:

config/dllHelper.js:

// config/dllHelper.js
const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
const dllConfig = require('./webpack.dll.config');

// 根據entry生成DllReferencePlugin列表
function genDllReferences() {
  return Object.keys(dllConfig.entry).map(
    name =>
      new webpack.DllReferencePlugin({
        manifest: require(path.join(
          __dirname,
          '../public/dll',
          `${name}.manifest.json`
        ))
      })
  );
}

// 生成dll文件的靜態資源路徑
function loadDllAssets() {
  return fs
    .readdirSync(path.resolve(__dirname, '../public/dll'))
    .filter(filename => filename.match(/.dll.js$/))
    .map(filename => `dll/${filename}`);
}

module.exports = {
  loadDllAssets,
  genDllReferences
};

config/webpack.dll.config.js:

// 
{
  ...
  output: {
    filename: '[name].[hash:8].dll.js'
  }
}

config/webpack.config.js:

const dllHelper = require('./dllHelper');
...
{
  plugins: [
    ...dllHelper.genDllReferences(),
    new HtmlIncludeAssetsPlugin({
      assets: dllHelper.loadDllAssets(), 
      append: false
    })
  ]
}

構建前清空文件夾

若DLLPlugiun的entry發生變化,則dll內的文件可能會愈來愈多,所以咱們須要在構建dll前清空文件夾,在這裏推薦這兩個package:

  • npm-run-all,在scripts可串行或並行執行script
  • rimraf,nodejs刪除文件利器

首先安裝相應依賴:yarn add -D rimraf npm-run-all,而後修改package.json:

scripts: {
  "make:dll": "npm-run-all clear:dll build:dll",
  "build:dll": "webpack --config config/webpack.dll.config.js --mode production",
  "clear:dll": "rimraf public/dll",
}

以後在變更DLL時,必定要記得執行:npm run make:dll

其餘

Demo倉庫地址:GitHub - vv13/react-dll-demo

相關文章
相關標籤/搜索