このすみノート

Webエンジニアが技術や趣味を書くブログです。

webpackのmodeは重要!難読化からMinifyまでする優れモノ

webpack4から、modeというオプションが追加されました。

https://webpack.js.org/concepts/mode/

このmodeオプションですが、多くの解説サイトにおいて、以下のように指定してくださいと解説されています。

  • 開発:development
  • 本番:production

何気なく指定されている方も多いかと思いますが、かなり重要なオプションです。JSの難読化からデータ容量の削減まで、各種最適化を行ってくれるオプションだからです。

modeの指定について

webpack4ではmodeが必須である

webpack4では、modeオプションを指定しないと、以下の警告が発生します。

WARNING in configuration

The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.

You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

modeオプションが明示的に指定されなかったので、production設定でビルドしましたと書いてあります。

webpack4でmodeを指定する方法

modeの指定は「webpack.config.js」で行ないます。開発用のビルド設定ファイルではdevelopmentを指定し、本番用のビルド設定ファイルではproductionを指定します。

webpack.config.js

module.exports = {
    // mode: development or production (or none)
    mode: 'development',

    // エントリーポイントの設定
    entry: './src/index.js',

    // 出力の設定
    output: {
        // 出力するファイル名(このファイルを起点にバンドルされていきます)
        filename: 'index.js',
        // 出力パス(最終的にpublic/js/bundle/index.jsに出力されます)
        path: __dirname + '/public/js/bundle/'
    },

    // 〜以下、省略〜
};

環境毎にmodeを切り替える方法

最もお手軽な方法は、ファイル単位で切り替えてしまう方法です。

  • 開発用:webpack.config.development.js
  • 本番用:webpack.config.production.js

また、webpack.config.jsは普通のJSでもありますので、内部で分岐して切り替えることも可能です。

私の場合は、環境変数で切り替えています。その際は、ビルドコマンドで環境変数を与えています。例えば、以下のようなコマンドを実行します。

WEBPACK_ENV=development webpack --colors --config webpack.config.js

そうすると、「WEBPACK_ENV」という環境変数に環境が入っているので、それをそのまま指定することができます。

webpack.config.js

module.exports = {
    mode: process.env.WEBPACK_ENV,

    // 〜以下、省略〜
}

毎回ハードコードで打ち込むのは大変ですので「package.json」に予めコマンドを登録しておくと便利です。

package.json

{                                                                                                         
    "scripts": {
        "build-dev": "WEBPACK_ENV=development webpack --colors --config webpack.config.js`",
        "build-prod": "WEBPACK_ENV=production webpack --colors --config webpack.config.js`"
    },
    // 〜以下、省略〜
}

これによって、以下のようなショートカットコマンドでビルドすることが可能です。

  • 開発用:npm run build-dev
  • 本番用:npm run build-prod

modeの効用

developmentでビルドした場合

開発設定でビルドすると、中身は割と読みやすいJavaScriptになっています。

f:id:konosumi:20180623021110p:plain

productionでビルドした場合

本番設定でビルドすると、最小化されたJavaScriptになっています。

f:id:konosumi:20180623022432p:plain

最小化と難読化

production設定では「UglifyJsPlugin」によるコードの最小化が行われています。

production

Provides process.env.NODE_ENV with value production. Enables FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin and UglifyJsPlugin.

引用:https://webpack.js.org/concepts/mode/

ビルドされた結果のJSファイルを見ると、変数名は「a」や「e」や「s」といった言葉に置き換えられていることが分かります。

中身をざっと見る限り、完璧な難読化ではありませんが、大体においてはこのレベルで充分に通用するかと思います。

本番ビルドではsource-mapを無効にすること

せっかく最小化をしたり難読化をしたとしても「source-map」が有効になっていては意味がありません。

module.exports = {
    // 本番ビルドでは指定しないこと!
    devtool: 'source-map',
}

SourceMapとは、ビルド前後のJSファイルの対応関係情報を持ったファイルです。開発段階では便利なのですが、せっかく変数名を「a」と変換したとしても、マッピングファイルを万が一参照されてしまうと全てが台無しです。

さいごに

JavaScriptの最小化や最適化は、人類の永遠の課題であり、意外と面倒だったりするのですが、webpackであればmodeオプションひとつでやってくれます。

これは便利ですので、必ず適切に指定した方が良いです。