Help us understand the problem. What is going on with this article?

DllPluginを使ってWebpackのビルド時間を改善する

概要

Webpackのビルド時間を改善する手法としてDllPluginを使ってビルド対象を分割するというものがあります。そのやり方を説明します。

DLLPluginとは

DLLPluginはWebpack公式にも紹介されている方法でビルド対象を分割する事によって劇的にビルドのパフォーマンスを改善してくれます。 https://webpack.js.org/plugins/dll-plugin/

DLLとはダイナミックリンクライブラリの略で、要するに動的にライブラリにリンクしてくれるということなので、事前にライブラリを別のbundleとしてビルドしておいて、それに含まれるライブラリに依存するバンドルは後からライブラリのbundleにリンクするという形を取ります。
これによりライブラリとライブラリを使う側のコードのビルドを分離できるので、都度ライブラリ側のコードをビルドしなくて良くなりビルドが速くなります。

導入

ライブラリ側のファイルのビルドと使う側のファイルを分けるので、webpackの設定は2つ書きます。同時にビルド用のnpmスクリプトも2つ用意します。ライブラリ側をvendorとし、ライブラリを使うアプリケーション側をappとします。

ライブラリ側のビルド

今回はライブラリを詰め合わせたビルドをvendorという名前で作っていきます。

webpack.vendor.js
const path = require('path');
const webpack = require('webpack');
const ManifestPlugin = require('webpack-manifest-plugin');

module.exports = {
  entry: {
    vendor: [
      'axios',
    ],
  },
  output: {
    path: path.resolve(__dirname, 'public/js'),
    filename: '[name]-[hash].js',
    hashDigestLength: 6,
    library: '[name]'
  },
  plugins: [
    new webpack.DllPlugin({
      /**
       * path
       * manifestファイルの出力先
       * [name]の部分はentryの名前に変換されるので今回はvendor
       */
      path: path.join(__dirname, 'public/js', '[name]-manifest.json'),
      /**
       * name
       * どの空間(global変数)にdll bundleがあるか
       * output.libraryに指定した値を使えばよい
       */
      name: '[name]'
    })
  ]
};

axiosを分離してビルドする設定を書きました。

これを実行すると
public/js/vendor-[hash].js
public/js/vendor-manifest.json
という2つのファイルが生成されます。

public/js/vendor-[hash].jsはビルド結果が入り、public/js/vendor-manifest.jsonの方にはDLLPluginでのリンク用の設定が吐き出されます。

{
  "vendor.js": "vendor-ee25a3.js"
}

ライブラリを使うコード側のビルド

app.jsにはaxiosを使うようなコードを予め書いておきます。

webpack.js
const webpack = require('webpack');

module.exports = {
  entry: {
    app:'./resources/js/app.js',
  },
  plugins: [
    new webpack.DllReferencePlugin({
      context: __dirname,
      manifest: require('./public/js/vendor-manifest'),
    }),
  ],
  ...  ...
}

これを実行するとapp-[hash].jsが生成されます。

このようにしてDllReferencePluginを使うことでDllPluginで作ったvendor側のファイルを動的に読み込むことができます。

npm script

上2つのビルドはそれぞれ別々に実行できます。最初は依存関係があるのでvendor、appの順にビルドしてください。

package.json

{
  "private": true,
  "scripts": {
    "build-app": "webpack --no-progress --hide-modules --mode=production --config=./webpack.js",
    "build-vendor": "webpack --no-progress --hide-modules --mode=production --config=./webpack.vendor.js"
  },
...  ...
}

これによって日々の開発ではapp.js側しかビルドしなくて良いのでビルドが早くなります。

HTML側での読み込み

依存関係に合わせて順番に読むようにして下さい。

<script src="js/vendor-[hash].js"></script>
<script src="js/app-[hash].js"></script>

DllPluginを使ってみて

実際のアプリケーションにDllPluginを導入したところビルド時間が約3分の2ほどに短くなったので、とてもおすすめです。またDllPluginの対象はパスを指定するだけなので外部のライブラリだけでなく開発中のコードもクラス単位でビルドを分離可能なので、枯れていてほとんど変更がない部分についてはどんどんDllPluginの対象にしていくというのが有効だと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした