KatsuYuzuのブログ

.NET の開発をメインとした日記です。

ASP.NET MVC 5 主要 JavaScriptライブラリのCDN、Fallbackまとめ

先日作ったWebサイトがモバイル向けだったのでjQueryやbootstrapの取得にCDNを使うようにしました。

今回はついでに少し足をのばして、上記のWebサイトに使ってないライブラリについてもまとめてみます。

対象

対象とするライブラリは、MVCプロジェクトを作成した時におおよそ*1標準で読み込まれている、また、それらに合わせて準備されているMicrosoft Ajax CDNにホストされているライブラリ、バージョンとします*2

  • jQuery, 1.11.1 or 2.1.1(IE8を含む場合は1.11.1、それ以外の場合は2.1.1)
  • jQuery.Validation, 1.13.0
  • Microsoft.jQuery.Unobtrusive.Validation, 3.2.2
  • Modernizr, 2.8.3
  • bootstrap, 3.2.0
  • Respond, 1.2.0
  • knockoutjs, 3.1.0

※記載している名称とバージョンはNuGetを想定

HTML

結果となるHTMLです。
CDNからファイルを取得して、次の行で確認を行いFallbackとして自身のサイトからファイルを取得しなおしています。ASP.NETを使う場合も使わない場合も、HTMLについては同じです。

<!DOCTYPE html>
<html>
<head>

<!-- bootstrap(CSS) -->
<link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap/3.2.0/css/bootstrap.min.css">

<!-- Modernizr -->
<script src="//ajax.aspnetcdn.com/ajax/modernizr/modernizr-2.8.3.js"></script>
<script>(window.Modernizr)||document.write('<script src="/bundles/modernizr"><\/script>');</script>

</head>
<body>
<!-- Webサイトのコンテンツ -->

<!-- jQuery -->
<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.11.1.min.js"></script>
<script>(window.jQuery)||document.write('<script src="/bundles/jquery"><\/script>');</script>

<!-- bootstrap(CSS) Fallback -->
<script type="text/javascript">
    $(document).ready(function () {
        if ($('body').css('color') != 'rgb(51, 51, 51)') {
            $("head").prepend('<link rel="stylesheet" href="/Content/bootstrap">');
        }
    });
</script>

<!-- jQuery.Validation -->
<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/jquery.validate.min.js"></script>
<script>(window.jQuery.validator)||document.write('<script src="/bundles/jqueryval"><\/script>');</script>

<!-- Microsoft.jQuery.Unobtrusive.Validation -->
<script src="//ajax.aspnetcdn.com/ajax/mvc/5.2.2/jquery.validate.unobtrusive.min.js"></script>
<script>(window.jQuery.validator.unobtrusive)||document.write('<script src="/bundles/jqueryvalunobtrusive"><\/script>');</script>

<!-- bootstrap -->
<script src="//ajax.aspnetcdn.com/ajax/bootstrap/3.2.0/bootstrap.min.js"></script>
<script>(window.jQuery.fn.modal)||document.write('<script src="/bundles/bootstrap"><\/script>');</script>

<!-- Respond -->
<script src="//ajax.aspnetcdn.com/ajax/respond/1.2.0/respond.js"></script>
<script>(window.respond)||document.write('<script src="/bundles/respond"><\/script>');</script>

<!-- knockoutjs -->
<script src="//ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"></script>
<script>(window.ko)||document.write('<script src="/bundles/knockout"><\/script>');</script>

</body>
</html>

ASP.NET

上記のように直接HTMLに記述しても構いませんが、ここではScriptBundleを使う方法を紹介します。ScriptBundleとRazorを組み合わせることで上記のHTMLが出力されます。
方法は簡単です。ScriptBundleのコンストラクタに対して仮想パスとCDNを指定し、CdnFallbackExpressionプロパティにFallbackの判断に使われる式を指定します。
注意点として、CDNを利用するライブラリに対してはファイルをまとめる機能が使えない*3こと、StyleBundleのFallbackには現バージョンでは対応されてない*4ことが挙げられます。

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle(
        "~/bundles/jquery",
        "//ajax.aspnetcdn.com/ajax/jquery/jquery-1.11.1.min.js")
        {
            CdnFallbackExpression = "window.jQuery"
        }.Include(
            "~/Scripts/jquery-{version}.js"));

    bundles.Add(new ScriptBundle(
        "~/bundles/jqueryval",
        "//ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/jquery.validate.min.js")
        {
            CdnFallbackExpression = "window.jQuery.validator"
        }.Include(
            "~/Scripts/jquery.validate.js"));

    bundles.Add(new ScriptBundle(
        "~/bundles/jqueryvalunobtrusive",
        "//ajax.aspnetcdn.com/ajax/mvc/5.2.2/jquery.validate.unobtrusive.min.js")
        {
            CdnFallbackExpression = "window.jQuery.validator.unobtrusive"
        }.Include(
            "~/Scripts/jquery.validate.unobtrusive.js"));

    bundles.Add(new ScriptBundle(
        "~/bundles/modernizr",
        "//ajax.aspnetcdn.com/ajax/modernizr/modernizr-2.8.3.js")
        {
            CdnFallbackExpression = "window.Modernizr"
        }.Include(
            "~/Scripts/modernizr-*"));

    bundles.Add(new ScriptBundle(
        "~/bundles/bootstrap",
        "//ajax.aspnetcdn.com/ajax/bootstrap/3.2.0/bootstrap.min.js")
        {
            CdnFallbackExpression = "window.jQuery.fn.modal"
        }.Include(
            "~/Scripts/bootstrap.js"));

    bundles.Add(new ScriptBundle(
        "~/bundles/respond",
        "//ajax.aspnetcdn.com/ajax/respond/1.2.0/respond.js")
        {
            CdnFallbackExpression = "window.respond"
        }.Include(
            "~/Scripts/respond.js"));

    bundles.Add(new ScriptBundle(
        "~/bundles/knockout",
        "//ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js")
        {
            CdnFallbackExpression = "window.ko"
        }.Include(
            "~/Scripts/knockout-{version}.js"));

    bundles.Add(new StyleBundle(
        "~/Content/bootstrap")
        .Include(
            "~/Content/bootstrap.css"));

    bundles.UseCdn = true;
    BundleTable.EnableOptimizations = true;
}

Razorでは通常と同じようにScripts.Renderを呼び出すだけです。CSSについては手書き\(^o^)/

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap/3.2.0/css/bootstrap.min.css">
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    @Scripts.Render("~/bundles/jquery")
    <script type="text/javascript">
        $(document).ready(function () {
            if ($('body').css('color') != 'rgb(51, 51, 51)') {
                $("head").prepend('<link rel="stylesheet" href="/Content/bootstrap">');
            }
        });
    </script>
    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/bundles/jqueryvalunobtrusive")
    @Scripts.Render("~/bundles/bootstrap")
    @Scripts.Render("~/bundles/respond")
    @Scripts.Render("~/bundles/knockout")
</body>
</html>

*1:選ぶテンプレートによって変わるのでおおよそとしています

*2:実際にはプラグインの取捨選択したものを公式からminでDLするケースやAngularJSもあると思いますよ

*3:Razor側を手書きして上手に式を書けば使えないこともないか

*4:FallbackがScriptとして処理されてしまう