Skip to content

MS_ASPNETBundleConfig

nishi_74322014 edited this page Aug 21, 2026 · 1 revision

ASP.NET の BundleConfig

概要

CSS や JavaScript など複数ファイルを、

  • 一つのファイルにまとめる機能(Bundle)
  • 空白や不要な文字を削除してファイルサイズを小さくする機能(Minification)

補足(この機能が生まれた背景と、現在の位置付け): Bundle &
Minification は、HTTP/1.1 時代の性能問題への対処である。

【HTTP/1.1 の制約】
   ブラウザは 1 ドメインあたり【同時 6 接続程度】しか張らない
     → CSS 5 個 + JS 20 個 = 25 リクエスト
     → 4~5 往復に分かれる。各往復に RTT がかかる
     → 【まとめれば速くなる】★ これが Bundle の動機

HTTP/2 以降、この前提が崩れた

HTTP/1.1 HTTP/2 / HTTP/3
同時リクエスト 6 程度 多重化(実質制限なし)
まとめる効果 大きい 小さい(むしろ逆効果のことも)
【HTTP/2 でまとめると不利になる理由】
   ・1 ファイルでも変更するとバンドル全体が【キャッシュ無効】になる
   ・使わないページのコードまで読み込む
   → 【適度に分割した方が良い】(コード分割)

とはいえ Minification(圧縮)は今も有効である。
現在は Bundle よりも以下が主流になっている。

現在の手段 内容
Vite / webpack / esbuild フロントエンド側のビルド ツール。コード分割・Tree Shaking
ESM(ネイティブ モジュール) ブラウザが import を直接解釈
LibMan クライアント ライブラリの取得のみ(バンドルはしない)
Microsoft.AspNetCore.SpaServices.Extensions SPA のビルドを .NET 側から起動
圧縮(gzip / Brotli) サーバ側で有効化。Minification より効く場合も

本ページの内容は、.NET Framework 版 ASP.NET の資産を
保守する際に必要な知識
として読むのが妥当である。
ASP.NET Core には System.Web.Optimization は存在しない

初期設定

以下をインストールする。

Install-Package Microsoft.AspNet.Web.Optimization

機能と設定

ASP.NET Web FormsASP.NET MVC で機能が若干異なるもよう。

詳しくは下記を参照。

Bundle & Minification

機能概要

CSS や JavaScript など複数ファイルを、

  • 一つのファイルにまとめる機能(Bundle)
  • 空白や不要な文字を削除してファイルサイズを小さくする機能(Minification)

を使用するには、BundleConfig ファイルへの定義が必要になる。

定義方法

基本的に、以下のステートメントを使用して定義を行う。

public static void RegisterBundles(BundleCollection bundles)
{
    // ( new ScriptBundle("~/XXXX") のパスは実在するpathと被るとRender時にバグる。
    // なので、bundlesと実在しないpathを指定している(CSSも同じbundlesを使用する)。

    bundles.Add(
      new ScriptBundle("~/バンドルしたファイルの仮想バス").Include(
          "~/バンドルするファイルの仮想パス 1",
          "~/バンドルするファイルの仮想パス 2",
          "~/バンドルするファイルの仮想パス 3",
          ・・・);

定義方法は、ASP.NET Web FormsASP.NET MVC で若干異なるもよう。

  • JS の設定

    • ASP.NET Web Forms では、ScriptBundle クラスと ScriptManager クラスを併用する。
    • ASP.NET MVC では、ScriptBundle クラスを使用する。
  • CSS の設定

    • ASP.NET Web Forms では、Bundle.config を使用する。
    • ASP.NET MVC では、ScriptBundle クラスではなく、StyleBundle クラスを使用する。

詳しくは下記を参照。

補足(コメントの「実在する path と被るとバグる」は重要): 原文の
コード中のコメントが記録しているこの落とし穴は実在する

【問題】
   bundles.Add(new ScriptBundle("~/Scripts/all.js")...)
      ↑ Scripts/all.js が【実際にディスク上に存在する】と

   → 静的ファイル ハンドラが先に応答してしまう
   → バンドルが効かない、または内容が混ざる

【対策】
   バンドルの仮想パスは【実在しないパス】にする
   慣例: "~/bundles/scripts"(拡張子も付けない)
// ○ 実在しないパス、拡張子なし
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
    "~/Scripts/jquery-{version}.js"));   // ← {version} でバージョン吸収

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

{version} プレースホルダは便利で、
NuGet でライブラリを更新してもコードを直さずに済む

.min.js の自動選択も覚えておく。

Scripts/jquery-3.7.0.js      ← デバッグ時に使われる
Scripts/jquery-3.7.0.min.js  ← リリース時に自動でこちらが選ばれる

 → 同名で .min が並んでいると、【最適化有効時に .min が優先】される

順序が保持されない場合がある点も注意する。
Include に書いた順に連結されるが、
IncludeDirectory やワイルドカードでは順序が保証されない
依存関係のある JS(jQuery → プラグイン)は
必ず個別に、順番に書く

CDNフォールバック

機能概要

Web には色々なフォールバックがあるが、

  • 効果的なフォールバック戦略の作成方法
    (リンク切れ:https://msdn.microsoft.com/ja-jp/library/hh273396.aspx

このうち、BundleConfig では、CDNフォールバックの機能を提供している。

CDNフォールバックには以下の様なメリットがある。

  • そのライブラリを、CDN経由の高速配信で受け取ることができる。
  • 他のサイトで同じファイルを使用する場合は、キャッシュを共有できる。
  • ライブラリ・ファイルを準備せずにコードを書き始めることができ。

定義方法

こちらも、ASP.NET Web FormsASP.NET MVC で機能が若干異なるもよう。

詳しくは下記を参照。

補足(CDN の「キャッシュ共有」の利点は失われた): 原文が挙げる
3 つのメリットのうち、2 番目は現在成立しない

【かつての想定】
   A サイトが CDN の jquery.min.js を読む → ブラウザがキャッシュ
   B サイトが【同じ URL】を読む → キャッシュから即座に取れる
     → 「みんなが CDN を使えば、初回だけで済む」

【現在(2020 年頃~)】
   ブラウザの HTTP キャッシュが【サイトごとに分離された】★
     (Cache Partitioning。Chrome 86、Safari、Firefox で実施)
     → 別サイトのキャッシュは【再利用されない】

【理由】 プライバシー(キャッシュの有無で訪問履歴が推測できた)

残る利点と、新たな欠点:

評価
高速配信(地理的に近い) 今も有効。ただし自サイトも CDN 経由なら差は小さい
キャッシュ共有 失われた
準備なしで書き始められる 有効(開発時)
サプライ チェーン リスク CDN が改竄されると全利用サイトに影響(新たな懸念)
可用性 CDN 障害でサイトが壊れる(フォールバックが要る理由)
プライバシー 利用者の IP が第三者に渡る(GDPR で問題視された事例あり)

**現在の推奨は「自サイトから配信する」**である。

・npm でインストールし、ビルドしてバンドルする
・CDN を使うなら【Subresource Integrity(SRI)を必ず付ける】
<script src="https://cdn.example.com/jquery.min.js"
        integrity="sha384-xxxxx"
        crossorigin="anonymous"></script>
<!-- ↑ ハッシュが一致しなければ実行されない(改竄検知) -->

CdnFallbackExpression の仕組み(原文の機能):

bundles.UseCdn = true;
var jquery = new ScriptBundle("~/bundles/jquery",
    "//ajax.aspnetcdn.com/ajax/jQuery/jquery-3.7.0.min.js")
    { CdnFallbackExpression = "window.jQuery" };
//                            ↑ これが undefined ならローカルを読み直す
bundles.Add(jquery);

フォールバック用のローカル ファイルも配置が要る点に注意する
(CDN だけに頼るとフォールバックできない)。

有効・無効の制御

Web.config で設定

デバッグの設定の場合は「無効」になっている。

Web.config の compilation 要素の debug 属性が true の場合、無効になる。

<compilation debug="true" targetFramework="4.5.2" />

プログラムから設定

プログラムから明確に有効・無効を制御できる。

BundleConfig に有効・無効を記述する。

BundleTable.EnableOptimizations = true;
BundleTable.Bundles.UseCdn = true; // 後述のCDNフォールバック有効・無効

移行メモ(原文の見出しの誤字): 原文は「プロムラムから設定」と
なっていたため、「プログラム」に修正した。

補足(この挙動が開発時の混乱の元になる):

【既定の挙動】
   debug="true"  → バンドルも Minify も【無効】(個別ファイルが出る)
   debug="false" → バンドル・Minify が【有効】

【なぜ debug 時は無効なのか】
   ・ブラウザの開発者ツールで元のファイルをデバッグしたい
   ・行番号がずれない

【なぜ混乱するのか】
   ・開発環境では動くのに、【本番でだけ壊れる】
      → JS の読み込み順、Minify で壊れるコード、相対パスの CSS
   ・逆に、本番の症状を開発環境で再現できない

対策: 本番相当の設定でも動作確認する

// 一時的に強制有効にして検証する
BundleTable.EnableOptimizations = true;

Minify で壊れる典型例:

// ✗ セミコロンの省略。連結時に前後の行と繋がって壊れる
var a = 1
var b = 2

// ✗ CSS の相対パス。バンドル後の仮想パスが変わり、画像が 404 になる
background: url(../images/bg.png);

CSS の相対パス問題には CssRewriteUrlTransform を使う。

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

リンクのさせ方

こちらも、ASP.NET Web FormsASP.NET MVC で機能が若干異なるもよう。

詳しくは下記を参照。

補足(キャッシュ バスティング): バンドルの参照は
ヘルパー経由で出力するのが要点である。

// ASP.NET MVC の Razor
@Scripts.Render("~/bundles/jquery")
@Styles.Render("~/Content/css")
<!-- 出力(最適化有効時) -->
<script src="/bundles/jquery?v=r0sfV2345LcOtvE4_UGGnQ0FRUBhFDzRfR1J6vgcbfk1"></script>
<!--                          ↑ 内容のハッシュ                                -->

?v= はバンドル内容のハッシュであり、

・内容が変われば URL が変わる → 【ブラウザが確実に取り直す】
・内容が同じなら URL も同じ  → 【長期キャッシュが効く】

→ キャッシュ バスティング(cache busting)と呼ばれる定石

ASP.NET Core での同等機能
asp-append-version タグ ヘルパーである。

<script src="~/js/site.js" asp-append-version="true"></script>
<!-- → /js/site.js?v=Ynv7Ur0... -->

手で <script src="..."> と書くと、この恩恵を失う
更新したのに古い JS が使われ続ける——という障害の
典型的な原因である。

参考

Microsoft Learn


Tags: 移行, .NET開発, ASP.NET, ASP.NET Web Forms, ASP.NET MVC

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally