🗜️

Angular で ng build するときにシンボルの minify を抑止する

に公開

ng build では JavaScript コードは minify される

Angular アプリケーションを ng build してリリース用ビルドを作成すると、minify された JavaScript ファイルが生成されます。つまり、オリジナルの JavaScript コードに対して、外部参照されない変数名や関数名などの各種シンボルを a とか b みたいな短い名前に変更したり、より短い形で表現できる形に式を変形したりして、コードのサイズを縮小するわけです。ファイルサイズが小さくなる、クライアントサイドでの読み込みが高速になる、という点では大変ありがたいのですが、そのように minify された JavaScript コードは、結果として、非常に解読困難なコードと化します。そのため、ちょっと困る局面もあります。

リリースビルドでしか再現しないバグ

ある日、開発環境では問題なく動作していたアプリケーションが、ステージング環境で挙動不審になるという現象に直面しました。どうやら、開発ビルドでは起きない、リリースビルド後にしか再現しないタイプのバグのようです。

このような場合、当然ながらブラウザの開発ツールを使ってデバッグを試みるのですが、minify された JavaScript が相手では、解決は困難を極めました。クラス名や変数名が ab などに置き換えられていますし、また、人間が読むようなことは想定されていないため、式や、場合によってはその順序すらも、積極的に入れ替えられ、書き換えられてしまっています。

ng build の minify を抑止する

そこで、ng build の際に minify を抑止する方法を調べてみたところ、どうやら環境変数 NG_BUILD_MANGLE に false を設定すれば良い、ということがわかりました。具体的には、例えば Bash シェルであれば以下のようにコマンドを実行します。

NG_BUILD_MANGLE=false

PowerShell なら以下ですね。

$env:NG_BUILD_MANGLE = "false"

このように環境変数を設定しておいてから ng build することで、クラス名や変数名がそのまま残った状態でリリースビルドが生成されるため、デバッグが非常にしやすくなります。

npm run スクリプトで楽をする

とはいえ、毎回シェルで環境変数を設定してから ng build を実行するのはちょっと面倒です。そこで、npm run のスクリプトにしてしまうのが便利です。こういうときに使えるのが、cross-env という npm パッケージです。

https://www.npmjs.com/package/cross-env

まずは cross-env を開発時依存としてインストールします。

npm install --save-dev cross-env

続いて、package.json の scripts セクションに以下のように記述します。

"scripts": {
  ...
  "build:nomangle": "cross-env NG_BUILD_MANGLE=false ng build"
}

これで、以下のコマンドを実行するだけで、minify を抑止した状態のリリースビルドが得られます。

npm run build:nomangle

おわりに

今回のように、リリースビルド後でないと再現しないバグに遭遇したとき、デバッグを円滑にするために ng build の minify を止める手段を知っておくと便利です。もちろん最終的には minify された状態で動作確認する必要がありますが、開発初期や検証段階では、あえて難読化を避けておくことで、問題の切り分けがぐっと楽になる場合もあります。

Discussion