ASP.NET 4.5 では、 System.Web.Optimization の機能を使用して 各javascriptやcssファイルを最小化し、1つのリソースにまとめてバンドルする機能が使用できます。今回はざっとした使い方を見てみます。もちろんリソースファイルのバンドルと最小化機能は ASP.NET Formだけでなく ASP.NET MVC でも使用できます。

検証環境

  • Visual Studio 2012
  • ASP.NET 4.5

Bundle機能を使用するにあたって参考にしたURLをいくつか記載しておきます。

Bundling and Minification
http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification
Adding Bundling and Minification to Web Forms
http://blogs.msdn.com/b/rickandy/archive/2012/08/14/adding-bundling-and-minification-to-web-forms.aspx

1.Visual Studio のプロジェクトを作成とバンドルの設定

最初に下図のように ASP.NET Web フォームアプリケーション プロジェクトテンプレートからプロジェクトを作成します。

作成された Global.asax のひな形をみると、下記のようにApplication_Startメソッド内で  BundleConfig.RegisterBundles メソッドの呼び出しが行われています。

        void Application_Start(object sender, EventArgs e)
        {
            // アプリケーションのスタートアップで実行するコードです
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterOpenAuth();
        }

実際の BundleConfig.cs 自体は プロジェクトの App_Start フォルダーに格納されています。空のWebアプリケーションからプロジェクトを作成した場合にバンドル機能を使えるようにするには 必要なdll参照の追加やNuGetからパッケージのインストールおよび Web.configの修正などが必要みたいです。詳細は未検証ですが。

BundleConfig.cs の実装は既定値では次のようになっていました。

        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/WebFormsJs").Include(
                  "~/Scripts/WebForms/WebForms.js",
                  "~/Scripts/WebForms/WebUIValidation.js",
                  "~/Scripts/WebForms/MenuStandards.js",
                  "~/Scripts/WebForms/Focus.js",
                  "~/Scripts/WebForms/GridView.js",
                  "~/Scripts/WebForms/DetailsView.js",
                  "~/Scripts/WebForms/TreeView.js",
                  "~/Scripts/WebForms/WebParts.js"));

            bundles.Add(new ScriptBundle("~/bundles/MsAjaxJs").Include(
                "~/Scripts/WebForms/MsAjax/MicrosoftAjax.js",
                "~/Scripts/WebForms/MsAjax/MicrosoftAjaxApplicationServices.js",
                "~/Scripts/WebForms/MsAjax/MicrosoftAjaxTimer.js",
                "~/Scripts/WebForms/MsAjax/MicrosoftAjaxWebForms.js"));

            // 開発に使用し、情報源である開発バージョンの Modernizr を使用します。続いて、
            // 運用の準備が完了したら、http://modernizr.com のビルド ツールを使用し、必要なテストのみを選択します
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                "~/Scripts/modernizr-*"));
        }

例えば、 jQuery もバンドルされるようにしたい場合は次のように追加します。

            bundles.Add(new ScriptBundle("~/bundles/jquery").Include("~/jquery-{version}.js"));
            bundles.Add(new ScriptBundle("~/bundles/jquery-ui").Include("~/jquery-ui-{version}.js"));

            // Web.config の <compilation>タグの debug 属性が false の場合に自動的にjs,cssが最小化されバンドル
            // されるようになる。プログラムから設定を上書きしたい場合は次のように記述する
            //BundleTable.EnableOptimizations = false;

System.Web.Optimizationは web.configの compilation タグの debug 属性 が false の場合に js,cssファイルの最小化とバンドル機能が動作します。プログラムからバンドル機能を使用するかの設定を上書きする場合は 上記サンプルコードのように BundleTable.EnableOptimizations を true や false を設定してください。

バンドルされたjavascriptやcss をページで読み込むには次のようにします。javascriptの場合は Scripts.Render, css の場合は Styles.Renderメソッドを使用します。

<head runat="server">
    <asp:PlaceHolder runat="server">
        <%: Scripts.Render("~/bundles/modernizr") %>
        <%: Scripts.Render("~/bundles/jquery") %>
        <%: Scripts.Render("~/bundles/jquery-ui") %>
        <%: Styles.Render("~/Content/css") %>
    </asp:PlaceHolder>
    <webopt:BundleReference runat="server" Path="~/Content/css" />
</head>

cssの場合は webopt:BundleReference コントロールを使用することもできるみたいです。ただし、このコントロールはMicrosoft.AspNet.Web.Optimization.WebFormsアセンブリをプロジェクトで参照している必要があります。

Bundle.config にバンドルの定義を記載することもできます。既定では次のように設定されています。

<?xml version="1.0" encoding="utf-8" ?>
<bundles version="1.0">
  <styleBundle path="~/Content/css">
    <include path="~/Content/Site.css" />
  </styleBundle>
  <styleBundle path="~/Content/themes/base/css">
    <include path="~/Content/themes/base/jquery.ui.core.css" />
    <include path="~/Content/themes/base/jquery.ui.resizable.css" />
    <include path="~/Content/themes/base/jquery.ui.selectable.css" />
    <include path="~/Content/themes/base/jquery.ui.accordion.css" />
    <include path="~/Content/themes/base/jquery.ui.autocomplete.css" />
    <include path="~/Content/themes/base/jquery.ui.button.css" />
    <include path="~/Content/themes/base/jquery.ui.dialog.css" />
    <include path="~/Content/themes/base/jquery.ui.slider.css" />
    <include path="~/Content/themes/base/jquery.ui.tabs.css" />
    <include path="~/Content/themes/base/jquery.ui.datepicker.css" />
    <include path="~/Content/themes/base/jquery.ui.progressbar.css" />
    <include path="~/Content/themes/base/jquery.ui.theme.css" />
  </styleBundle>
</bundles>

Site.master マスターページで次のように使用されています.

<head>
    <webopt:BundleReference runat="server" Path="~/Content/css" />
</head>

その他、<%: Styles.Render("~/bundles/common" %> のように Placeholder コントロールに記述することもできます。

2.結果の確認

Web.configのcompilationタグのdebug属性をfalseにしてデバッグ実行すると例えば次のようなマークアップが出力されます。

<script src="/Scripts/modernizr-2.5.3.js"></script>
<script src="/Scripts/jquery-1.7.1.js"></script>
<script src="/Scripts/jquery-ui-1.8.20.js"></script>
<link href="/Content/Site.css" rel="stylesheet"/>

一方debug属性がtrueの場合以下のようなマークアップが生成されます。分かりずらいですが、 jquery-1.7.1.min.js が読み込まれています。 デバッグモードの場合は jquery-1.7.1.js が参照されます。これは、開発者ツールでソースを確認していただくと分かります。

<script src="/bundles/modernizr?v=jmdBhqkI3eMaPZJduAyIYBj7MpXrGd2ZqmHAOSNeYcg1"></script>
<script src="/bundles/jquery?v=wBUqTIMTmGl9Hj0haQMeRbd8CoM3UaGnAwp4uDEKfnM1"></script>
<script src="/bundles/jquery-ui?v=Cw2yi596KkdaXwiCw0hcihY771buayEuXXWppd89Tsk1"></script>
<link href="/Content/css?v=f5ydPh92LWsttS1MEc8JZmFtAgT6RUaer_jy37xBkQs1" rel="stylesheet"/>

3.補足:開発者ツールを使用したバンドルされたjavascriptのデバッグ

javascriptがバンドルされて最小化されうと不要なコメントや空白が除去されるため、javascriptを見ても内容が非常にわかりづらくなります。バンドルおよび最小化されたjavascriptを開発者ツールを使用してデバッグしやすくする方法を記載します。バンドルと最小化されたjavascriptをデバッグしたい場合は開発者ツールで、スクリプトタブを表示して、下図のように読み込まれているスクリプトを展開してデバッグするスクリプトを選択します。

例えば 下図のようなスクリプトが表示されます。そのままでは非常に可読性がわるいです。

最小化されたスクリプトは可読性が悪いので下図のように 構成をクリックして表示されるメニューからJavascriptの書式設定を選択します。

コードが整形されて読みやすくなります。最小化されたscriptをデバッグするよりははるかにソースの解析が簡単になります。

開発者ツールの右側のテキストボックスでスクリプト内を検索することもできます。

4.まとめ

説明は以上です。System.Web.Optimizationの機能を使用することで特別なツールを使用することなく、リリースモードのときのみリソースをバンドルして最小化することができるようになります。バンドル機能を使用するとCDNを使わない状態でもある程度、リクエスト数減少と応答サイズの減少によりレスポンスを高速化しパフォーマンスの向上を期待することができるようになります。