かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その54 )( webpack を 3.8.1 → 4.9.1 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その53 )( Gradle を 3.5 → 4.6 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • webpack を 3.8.1 → 4.9.1 へバージョンアップします。

参照したサイト・書籍

目次

  1. webpack を 3.8.1 → 4.9.1 へバージョンアップする
  2. npm run build コマンドを実行してみる
  3. webpack-cli をインストールする
  4. 再び npm run build コマンドを実行してみる
  5. uglifyjs-webpack-plugin を 1.2.2 → 1.2.5 へバージョンアップする
  6. webpack.config.js を変更する
  7. package.json を変更する
  8. cross-env をアンインストールする
  9. 動作確認
  10. webpack.config.js から optimization、devtool の設定を取り除くとどうなるのか?

手順

webpack を 3.8.1 → 4.9.1 へバージョンアップする

npm install --save-dev webpack@4.9.1 コマンドを実行します。

f:id:ksby:20180527204920p:plain

npm run build コマンドを実行してみる

バージョンアップしただけで webpack.config.js は何も修正していない状態で npm run build コマンドを実行してみます。

f:id:ksby:20180527211011p:plain

CLI が別のパッケージになったので webpack-cli か webpack-command をインストールするようメッセージが出力されました。webpack-cli と webpack-command の違いは webpack-command サイト内の Differences With webpack-cli に記述があります。

今回は webpack-cli をインストールします。

webpack-cli をインストールする

npm install --save-dev webpack-cli コマンドを実行します。

f:id:ksby:20180527211732p:plain

再び npm run build コマンドを実行してみる

再び npm run build コマンドを実行してみます。

f:id:ksby:20180527212056p:plain f:id:ksby:20180527212149p:plain

webpack 4 から追加された --mode オプションを指定していないので、WARNING のメッセージが出力されました。

webpack 3 → 4 へのマイグレーション関連の記事を Web で調べて、以下の点を変更することにします。

  • webpack を実行している npm scripts に --mode オプションを追加します。
  • cross-env パッケージが不要になるのでアンインストールします。
  • webpack 4 では --mode development が指定されている時には最適化処理が実行されず、--mode production が指定されている時には最適化処理が実行されるようになったので、Uglify の設定を変更します。
  • uglifyjs-webpack-plugin をインストールしなくても --mode production が指定されていると Uglify されるのですが、デフォルトの設定では console.log() が削除されないようなので、uglifyjs-webpack-plugin をインストールしたままにして独自に設定することにします。また uglifyjs-webpack-plugin を最新版にバージョンアップします。

uglifyjs-webpack-plugin を 1.2.2 → 1.2.5 へバージョンアップする

npm install --save-dev uglifyjs-webpack-plugin@1.2.5 コマンドを実行します。

f:id:ksby:20180528014124p:plain

webpack.config.js を変更する

webpack.config.js の以下の点を変更します。

const webpack = require("webpack");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

// --mode オプションで指定された文字列を参照したい場合には argv.mode を参照する
module.exports = (env, argv) => {
    return {
        entry: {
            "js/inquiry/input01": ["./src/main/assets/js/inquiry/input01.js"],
            "js/inquiry/input02": ["./src/main/assets/js/inquiry/input02.js"],
            "js/inquiry/input03": ["./src/main/assets/js/inquiry/input03.js"],
            "js/inquiry/confirm": ["./src/main/assets/js/inquiry/confirm.js"]
        },
        output: {
            path: __dirname + "/src/main/resources/static",
            publicPath: "/",
            filename: "[name].js"
        },
        resolve: {
            modules: [
                "node_modules",
                "src/main/assets/js"
            ],
            alias: {
                jquery: "jquery"
            }
        },
        module: {
            rules: [
                {
                    test: /\.js$/,
                    exclude: [
                        /node_modules/,
                        /jquery.autoKana.js$/
                    ],
                    loader: "eslint-loader"
                }
            ]
        },
        optimization: {
            minimizer: [
                new UglifyJsPlugin({
                    uglifyOptions: {
                        compress: true,
                        ecma: 5,
                        output: {
                            comments: false
                        },
                        compress: {
                            dead_code: true,
                            drop_console: true
                        }
                    },
                    sourceMap: false
                })
            ]
        },
        plugins: [
            new webpack.ProvidePlugin({
                $: "jquery",
                jQuery: "jquery"
            })
        ],
        devtool: "inline-source-map"
    };
};
  • const isProduct = process.env.NODE_ENV === "product"; を削除します。
  • --mode オプションで指定されたモードを参照できるようにするために、module.exports = { ... };module.exports = (env, argv) => { return { ... }; }; に変更します。これで argv.mode--mode オプションで指定された文字列を参照できるようになります。
  • optimization: { ... } を追加し、ここに UglifyJsPlugin の設定を記述します。optimization: { ... } の設定は --mode development の時には適用されず(Uglify や sourceMap出力が行われません)、--mode production の時のみ適用されるようです(Uglify や sourceMap出力が行われます)。また ecma: 6 にすると IE11 で入力画面2の郵便番号を入力してヒットした候補をドロップダウンリストに表示する機能が動作しなかったので、ecma: 5 にします。
  • plugins: [ ... ] から .concat(isProduct ? [new UglifyJsPlugin()] : [] を削除します。
  • devtool: "inline-source-map" は残します。残しておかないとソースが変わりすぎて Chrome で debug しにくそうに思えたからです。optimization: { ... } で UglifyJsPlugin の設定も記述しておくと --mode production の時に sourceMap が残りません。

ちなみに console.log() が残ることを気にしなければ、optimization: { ... } の設定がなくても --mode production を指定すれば Uglify は行われます。

package.json を変更する

package.json の以下の点を変更します。

  "scripts": {
    ..........
    "webpack:build": "webpack --mode production",
    "webpack:watch": "webpack --mode development --watch",
    ..........
    "build": "run-s clean:cssjs-dir postcss:build webpack:build"
  },
  • webpack:build のコマンドを webpackwebpack --mode production に変更します。
  • webpack:watch のコマンドを webpack --watchwebpack --mode development --watch に変更します。
  • build のコマンドを cross-env NODE_ENV=product run-s ...run-s ... に変更します。

cross-env をアンインストールする

npm uninstall --save-dev cross-env コマンドを実行します。

f:id:ksby:20180529004519p:plain

動作確認

tomcat を起動した後、npm run springboot コマンドを実行してみます。

f:id:ksby:20180529012848p:plain f:id:ksby:20180529012900p:plain

生成された js ファイルを見るとファイルサイズが全て 700KB 以上あり、ファイルを開いてみても Uglify はされておらず、ソースはほぼそのまま残っています。

f:id:ksby:20180529013137p:plain

http://localhost:9080/inquiry/input/01/ にアクセスして入力画面1~3まで操作してみましたが、特に問題はありませんでした。

今度は npm run build コマンドを実行してみます。

f:id:ksby:20180529015031p:plain f:id:ksby:20180529015205p:plain

生成された js ファイルがほぼ 100KB 以下になり、ファイルを開いてみると Uglify されています。

f:id:ksby:20180529015339p:plain

http://localhost:8080/inquiry/input/01/ にアクセスして(ポート番号を 9080 → 8080 に変更して Tomcat に直接アクセスしています)入力画面1~3まで操作してみましたが、特に問題はありませんでした。

src/test/groovy/ksbysample/webapp/bootnpmgeb/web/inquiry/InquiryInputControllerTest.groovy の失敗するテストをコメントアウトした後、clean タスク実行 → Rebuild Project → build タスクを実行してみます。

f:id:ksby:20180602124044p:plain

BUILD SUCCESSFUL のメッセージが出力されました。

問題なさそうですので、このまま 4.9.1 を使います。書き終わった時には 4.10.2 までバージョンが上がっていましたが。。。

webpack.config.js から optimization、devtool の設定を取り除くとどうなるのか?

optimization、devtool の設定を書かない時の動作もメモしておきます。

webpack.config.js から optimization、devtool の設定を削除します。

        ..........
        module: {
            rules: [
                {
                    test: /\.js$/,
                    exclude: [
                        /node_modules/,
                        /jquery.autoKana.js$/
                    ],
                    loader: "eslint-loader"
                }
            ]
        },
        plugins: [
            new webpack.ProvidePlugin({
                $: "jquery",
                jQuery: "jquery"
            })
        ]
    };
};

まずは --mode development である npm run springboot を実行してみます。

f:id:ksby:20180602125908p:plain f:id:ksby:20180602130010p:plain

optimization、devtool の設定を入れていた時は生成された js ファイルは 700KB以上ありましたが、今回は 300~400KB程度になりました。

生成された js ファイルを開いてみると、実行コードは改行コードが \r\n に変換されて eval( ... ); で囲まれるようです。

f:id:ksby:20180602130454p:plain

Tomcat を起動してから、Chromehttp://localhost:8080/inquiry/input/01/ にアクセスして DevTools で input01.js を開いてみると、eval( ... ); のまま表示されて、これだと debug をどうやればよいのかちょっと分かりませんでした。

f:id:ksby:20180602131630p:plain

sourceMap もたぶん出力されていませんね。ファイルサイズが小さいのはその辺が理由でしょう。

次に --mode production である npm run build を実行してみます。

f:id:ksby:20180602132306p:plain f:id:ksby:20180602132429p:plain

ファイルサイズは optimization、devtool の設定を入れていた時より数KBだけ大きいです。

生成された js ファイルを開いてみると、Uglify されていますがコメントが完全に削除されずに一部残っていました。

f:id:ksby:20180602132723p:plain

Tomcat を起動してから、Chromehttp://localhost:8080/inquiry/input/01/ にアクセスして動作確認してみましたが、IE11 でも入力画面2の郵便番号を入力してヒットした候補をドロップダウンリストに表示する機能が動作しましたし、他にも問題はありませんでした。

また console.log(...); も入れていると削除されません(これは実際に書いて試してみました)。

今のところ、個人的には optimization、devtool の設定は書く方が好みですね。webpack 4 の設定がまだよく分かっていないだけかもしれませんが。

履歴

2018/06/02
初版発行。