-
Notifications
You must be signed in to change notification settings - Fork 0
MS_ASPNETBundleConfig
- 戻る(ASP.NET)
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.ExtensionsSPA のビルドを .NET 側から起動 圧縮(gzip / Brotli) サーバ側で有効化。Minification より効く場合も 本ページの内容は、.NET Framework 版 ASP.NET の資産を
保守する際に必要な知識として読むのが妥当である。
ASP.NET Core にはSystem.Web.Optimizationは存在しない。
以下をインストールする。
Install-Package Microsoft.AspNet.Web.OptimizationASP.NET Web Forms と ASP.NET MVC で機能が若干異なるもよう。
詳しくは下記を参照。
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 Forms と ASP.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 Forms と ASP.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 Forms と ASP.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 が使われ続ける——という障害の
典型的な原因である。
-
特集:ASP.NET 4.5新機能概説(1):Visual Studio 2012の新機能とASP.NET 4.5のコア機能 (3/4) - @IT
https://atmarkit.itmedia.co.jp/ait/articles/1303/08/news072_3.html -
【ASP.NET MVC】BundleConfigを3点ほど勘違いしていたのでまとめ - modest violet
https://shin21.hatenablog.com/entry/2016/08/10/100000 -
Bundling and Minification | The ASP.NET Site
https://learn.microsoft.com/ja-jp/aspnet/mvc/overview/performance/bundling-and-minification
- ASP.NET Core での静的資産のバンドルと縮小
https://learn.microsoft.com/ja-jp/aspnet/core/client-side/bundling-and-minification - ASP.NET Core での静的ファイル
https://learn.microsoft.com/ja-jp/aspnet/core/fundamentals/static-files - LibMan(クライアント側ライブラリ マネージャー)
https://learn.microsoft.com/ja-jp/aspnet/core/client-side/libman/
Tags: 移行, .NET開発, ASP.NET, ASP.NET Web Forms, ASP.NET MVC
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。