Angular で ng build するときにシンボルの minify を抑止する
ng build では JavaScript コードは minify される
Angular アプリケーションを ng build してリリース用ビルドを作成すると、minify された JavaScript ファイルが生成されます。つまり、オリジナルの JavaScript コードに対して、外部参照されない変数名や関数名などの各種シンボルを a
とか b
みたいな短い名前に変更したり、より短い形で表現できる形に式を変形したりして、コードのサイズを縮小するわけです。ファイルサイズが小さくなる、クライアントサイドでの読み込みが高速になる、という点では大変ありがたいのですが、そのように minify された JavaScript コードは、結果として、非常に解読困難なコードと化します。そのため、ちょっと困る局面もあります。
リリースビルドでしか再現しないバグ
ある日、開発環境では問題なく動作していたアプリケーションが、ステージング環境で挙動不審になるという現象に直面しました。どうやら、開発ビルドでは起きない、リリースビルド後にしか再現しないタイプのバグのようです。
このような場合、当然ながらブラウザの開発ツールを使ってデバッグを試みるのですが、minify された JavaScript が相手では、解決は困難を極めました。クラス名や変数名が a
や b
などに置き換えられていますし、また、人間が読むようなことは想定されていないため、式や、場合によってはその順序すらも、積極的に入れ替えられ、書き換えられてしまっています。
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 パッケージです。
まずは 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