喜帳面の日記

50歳越えおやじのASP.NET MVC への挑戦日記です。

Visual Studio Express 2012 for Web でいってみる 7.Bundling and Minification

 

asp.net MVC4の「Bundling and Minification」にチャレンジしてみます。

「Bundling 」は、JavaScriptファイルやCSSファイルを1つのファイルにまとめ上げる機能で、「Minification」は改行や空白をカットしスクリプトサイズを圧縮する機能のようです。その結果、データ容量やクライアントからのリクエスト回数を最小化することができる。らしい。

参考資料は

 と、以下の書籍の付録 A.2.8 を参考にしました。
プログラミング MICROSOFT ASP.NET4 (Microsoft Press)

プログラミング MICROSOFT ASP.NET4 (Microsoft Press)


やってみたこと
1.スクリプトを配置
[Scripts]フォルダ下に[Myscripts](任意)を追加し自作JavaScriptファイルを追加。
MyJavaScript1.js と tooltip.js の2ファイル。

f:id:SannomiyaNotes:20120927212930p:plain

MyJavaScript1.jsにはfunction[myfc_replabel]が含まれています。
function myfc_replabel() {
  var targets = document.querySelectorAll("label"); //"label"要素を抽出し
  for (var i = 0; i < targets.length ; i++) {       //新しいlabel値に置き換える
      targets.item(i).innerHTML = _Myfc_getnewabel(targets.item(i).innerHTML);
      }
  }

function _Myfc_getnewabel (labelvalue) {
       return ("Rep-" + labelvalue);
  }
2.上記のスクリプトを使用するviewを用意。
今回は、標準のログイン画面をテスト用に変更してみました。
[Account]-[Login.cshtml]で1で追加したスクリプト内のfunction[myfc_replabel]を呼び出すように改造しました。
 ...省略...
<section id="loginForm">
<h2>ローカル アカウントを使用してログインします。</h2>
@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

 @* Bundlテスト用に追加 ここから*@
<script src="@Url.Content("~/Scripts/Myscripts/MyJavaScript1.js")" type="text/javascript"></script>
<input type="button" value="テスト実行" onclick="myfc_replabel()" />
 @* Bundlテスト用に追加 ここまで*@
   
    <fieldset>
        <legend>ログイン フォーム</legend>
...省略...
実行結果はこんな感じです。

f:id:SannomiyaNotes:20120927212534p:plain

 
3.Bundl指定を記述してみる。
[App_Start]-[BundleConfig.cs]を編集
BundleConfigクラスに以下の行を追加。
 
bundles.Add(new ScriptBundle("~/bundles/myScript").Include(
              "~/Scripts/Myscripts/*.js"));
編集する場所はこのあたりです。

f:id:SannomiyaNotes:20120927223140p:plain

意味的には「/Scripts/Myscripts内の拡張子jsのファイルを"~/bundles/myScript"って名前で1つに束ねる」ってかんじでしょうか。メソッドの詳細については前述のURLを参照ください。「jquery-{version}.js」こんな記述ができるのでnugetで最新versionのjqueryファイルに置き換えても、もんだいなーし、という仕組みですね。
 
4.@Scripts.Render指定を記述してみる。
 ここまでくると、先のLogin.cshtmlのJavaScriptファイルの指定部分を「@Scripts.Render」に書き換え可能になります。
今回の例では、先ほどテスト用に追加したJavaScriptファイルの指定部分、
<script src="@Url.Content("~/Scripts/Myscripts/MyJavaScript1.js")" type="text/javascript"></script>
と直接スクリプトを指定していた部分を削除して
html最終部分にある@section Scriptsに @Scripts.Render("~/bundles/myScript")を追加。
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/bundles/myScript")
}

f:id:SannomiyaNotes:20120927223749p:plain

 ここの部分をデバッグ実行のF12でhtmlソースをみてみると

<script src="/Scripts/Myscripts/MyJavaScript1.js"></script>
<script src="/Scripts/Myscripts/tooltip.js"></script>
この2行に置き換えられています。

 

5.Minification指定を記述してみる。
 [Global.asax]の[Application_Start]に

BundleTable.EnableOptimizations = false;

の1行を追加します。まずはfalseで試してみます。

f:id:SannomiyaNotes:20120928113519p:plain

この状態で、デバッグ実行してみます。
ログイン画面が表示されたところでF12を押して[スクリプト]を選択。

f:id:SannomiyaNotes:20120928114842p:plain

 @Scripts.Render("~/bundles/myScript")の記述が
<script src="/Scripts/Myscripts/MyJavaScript1.js"></script>
<script src="/Scripts/Myscripts/tooltip.js"></script>
の2行に置き換えられていることがわかります。
また、ソースは普通に読み取りができる状態で表示されています。

f:id:SannomiyaNotes:20120928122330p:plain

尚、発行を行ったリリース環境でも同じ結果となりました。
次に圧縮してみます。

BundleTable.EnableOptimizations = true;

同様にF12でスクリプトを表示すると

f:id:SannomiyaNotes:20120928123705p:plain

BundleTable.EnableOptimizations = false;では
<script src="/Scripts/Myscripts/MyJavaScript1.js"></script>
<script src="/Scripts/Myscripts/tooltip.js"></script>
この2行だったのが
BundleTable.EnableOptimizations = true;とすると
 <script src="/bundles/myScript?v=3qhhSepzMAh6iYWXkTO8HQhYbV0DvR0JifymbwA83o01"></script>
の1行にまとめられれます。
jquery関連も同様に圧縮されていることがわかります。
ソースは以下のように改行や空白が削除された状態になってます。

f:id:SannomiyaNotes:20120928124108p:plain


以上、Bundling and Minificationは

 1.Bundl指定

[App_Start]-[BundleConfig.cs]のBundleConfigクラスにBundl指定を追加。
 
2.圧縮指定
[Global.asax]の[Application_Start]に

BundleTable.EnableOptimizations = true;

の記述を追加する

以上2ステップでOKな感じです。

 尚、各種資料では、プロジェクト直下の[Web.config]の

<compilation targetFramework="4.5" debug="true"/>を圧縮時は

debug="false"にするように記述されていますが、

debug="true"のままでVS Webで「発行」をするとリリース環境の[Web.config]では

<compilation targetFramework="4.5" />とdebug= 以降が削除されているので、気にしなくてもいいのかもしれませんね。

(追記2014/04/10 削除してくれるわけは、Web.Release.configの 

compilation xdt:Transform="RemoveAttributes(debug)" ですね。)

 

もう1点。

リリースサイトのScriptsフォルダから当該スクリプトファイルを削除してもいいか?

これはダメ実行時にエラーとなります。

詳細は未確認ですが、ページへのアクセス都度動的にスクリプト圧縮してクライアントに送信しているのでしょうか?

 

スクリプトサイズを静的に圧縮したい場合は別途、minファイルを用意するってことになるんでしょうかね。参考ページの記述によると、minファイルがある場合、リリース環境にはminファイルを使用し、デバッグ時はminがつていないファイルが使用されるように記述されていたような気がする。(ごめん未確認です)

 

minファイルの作成についてのメモ書き

作成ツールはいくつかあるようですが、私の場合は「Microsoft Ajax Minifier」ってのを使ってみました。

参考:http://ajaxmin.codeplex.com//

nugetにもありましたね。

http://nuget.org/packages/AjaxMin

nugetからインストールすると[AjaxMin.dll]というファイルが[bin]フォルダにセットされる?件もまだ未確認です。

http://ajaxmin.codeplex.com// からダウンロードしてみました。

インストールしようとするとダウンロードした人が少なすぎるってエラーメッセージがでて驚きましたが、nugetからダウンロードする人の方が多いのかも。

 どっちからインストールしても、コマンドプロンプトからminファイルをつくるんだろう、対話形式は多分無い。と思ってます。

以降、Ajax Minifierは別途改めてチャレンジ結果を記載したいと思います。

 

追記<2014/04/10>----------------------

EnableOptimizationsの設定で、Releaseコンパイル時は圧縮して、debug時は圧縮しないようにするには、条件付きコンパイル・ディレクティブ(#ifディレクティブ)を使う方法が便利です。

//Releaseでコンパイル時はスクリプト圧縮する

    BundleTable.EnableOptimizations = true; //スクリプト圧縮する

#if DEBUG

     //DEBUGでコンパイル時はスクリプト圧縮しない

    BundleTable.EnableOptimizations = false;//スクリプト圧縮しない

#endif