ASP.NET MVCでデバッグ・リリースビルドごとにバンドル・縮小設定切り替え

ASP.NET MVCではJavaScriptファイルやCSSファイルを一つにまとめて1行にぎゅっとまとめてくれる機能がある。
英語の原題はBundling & minification、日本語だとバンドルと縮小というドキュメントが公式に。

具体的には、こういった2つのjsファイルがあるとして、もろもろ設定するとこれが一つのjsにまとまり、かつ改行とかを全てとっぱらってくれるというもの。
よく見かける、いわゆる「min.js」化をフレームワークがやってくれる。

a.js
function hello(){
  console.log("hello!");
}
b.js
function goodbye(){
  console.log("bye!");
}

そしてBundleConfig.csで以下のように定義する。
ローカルのScripts以下にあるa.jsとb.jsをまとめて、リリース時にはbundles/myjsという名前で参照できるようになる。

BundleConfig.cs
public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/myjs").Include(
                 "~/Scripts/a.js",
                 "~/Scripts/b.js"));
}

ビューでは次のような感じで上記の~/bundles/○○を読み込むようにコードを記載する。
@Scripts.Render(BundleConfig.csに書いた~/bundles/ファイル名)

Layout.cshtml
@using System.Web.Optimization
<!DOCTYPE html>
<html>
    <head>
        <title>@ViewBag.Title</title>
        <meta charset="utf-8" />
        @Scripts.Render("~/bundles/myjs")
    </head>
    <body>
        @RenderBody()
    </body>
</html>

さらに、この機能が有効になるように設定を入れる必要がある。
設定を入れなければ、普通にビルドしても読み込むjsファイルは何も加工されない姿(a.jsとb.jsそれぞれ定義される形)で取り込まれる。
機能を有効にするには以下2通りのやり方がある。

1.BundleCongfig.csの修正
2.Web.configの修正

BundleConfig.csのRegisterBundlesメソッドの中で以下のBundleTable〜の行を追加する。

BundleConfig.cs
public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/myjs").Include(
                 "~/Scripts/a.js",
                 "~/Scripts/b.js"));
    BundleTable.EnableOptimizations = true;
}

これを書いておくことで、デバッグビルドでもリリースビルドでもデバッグ開始ボタンを押した時常にバンドル・縮小機能が有効化される。

次にWeb.configで切り替える方法。
以下の定義を追加する。

Web.config
<system.web>
   <compilation debug="true" />
</system.web>

Web.configのやり方だとデバッグ実行時はバンドル・縮小機能が有効にならない。
リリースビルドに設定して「デバッグを開始」ボタンでは有効になると思いきや、実は有効にならない。
Web.configで設定した場合は「ctrl+F5」の「デバッグなしで実行」をした時に有効化される。

機能が有効になったら実際に出力されるhtmlは以下のようになる。

<html>
<head>
    <title></title>
    <meta charset="utf-8">
    <script src="/bundles/myjs?v=なんか長い文字列"></script>
</head>
<body>
    <h2>Welcome to ASP.NET MVC 5.2 on Mono!</h2>
</body>
</html>

中身を見ると以下のように2つあったjsファイルが1つになり、かつ余分な改行などがキュッと縮小され1行にまとまっていることがわかる。

/bundles/myjs
function hello(){console.log("hello!")}function goodbye(){console.log("bye!")}

例で示したファイルが少量のコードしかないのであまり恩恵が無い感じになっているが、これが大規模なコードになってくると1つのファイルにまとめることでファイルサイズが小さくなって読み込みが早くなるなど旨味が出てくる。

だがしかし。
デバッグビルドとリリースビルドでいちいち設定書き換えるのがめんどくさい。
デバッグ実行時は生のjsでブラウザ上でブレイクポイントを貼ったりしてデバッグしたい。
これをバンドル・縮小されたコードでやるのは苦行。というか無理。

なので、デバッグ実行時はバンドル・縮小を無効にし、リリースビルドしたらちゃんとバンドルしても動くというのを確認したい。
これが実現できたのが以下のようなやり方。

BundleConfig.cs
public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/myjs").Include(
                 "~/Scripts/a.js",
                 "~/Scripts/b.js"));
    #if DEBUG
    BundleTable.EnableOptimizations = false;
    #else
    BundleTable.EnableOptimizations = true;
    #endif
}

#if DEBUGとBundleConfig.cs上での設定を組み合わせた形。
これで少し幸せになれそう。