バンドルし、縮小の ASP.NET Core で静的なアセットBundle and minify static assets in ASP.NET Core

によってScott AddieDavid 松By Scott Addie and David Pine

この記事では、バンドルや縮小、これらの機能を使用して ASP.NET Core web アプリの使用方法などを適用する利点について説明します。This article explains the benefits of applying bundling and minification, including how these features can be used with ASP.NET Core web apps.

新機能のバンドルと縮小What is bundling and minification

バンドルと縮小は、web アプリに適用できる 2 つの個別のパフォーマンス最適化です。Bundling and minification are two distinct performance optimizations you can apply in a web app. を一緒に使用バンドルと縮小パフォーマンス向上のサーバー要求の数を減らすと、要求された静的なアセットのサイズを小さきます。Used together, bundling and minification improve performance by reducing the number of server requests and reducing the size of the requested static assets.

バンドルと縮小は、最初のページ要求の読み込み時間を向上させる主にします。Bundling and minification primarily improve the first page request load time. Web ページを要求されたら、ブラウザーは、静的なアセット (JavaScript、CSS、およびイメージ) をキャッシュします。Once a web page has been requested, the browser caches the static assets (JavaScript, CSS, and images). その結果、バンドルと縮小しないパフォーマンスを向上させる、同じページで、または同じ資産を要求するのと同じサイト上のページを要求するときにします。Consequently, bundling and minification don't improve performance when requesting the same page, or pages, on the same site requesting the same assets. 場合、有効期限が切れる資産にヘッダーが正しく設定されていないし、バンドルと縮小が使用されていない場合、ブラウザーの鮮度ヒューリスティック マーク資産古い数日後。If the expires header isn't set correctly on the assets and if bundling and minification isn't used, the browser's freshness heuristics mark the assets stale after a few days. さらに、ブラウザーでは、各資産の検証要求が必要です。Additionally, the browser requires a validation request for each asset. この場合は、バンドルと縮小は、最初のページ要求した後でもパフォーマンスの向上を提供します。In this case, bundling and minification provide a performance improvement even after the first page request.

バンドルBundling

1 つのファイルに複数のファイルを結合バンドルします。Bundling combines multiple files into a single file. バンドルは、web ページなどの web アセットを表示するために必要なサーバー要求の数を減らします。Bundling reduces the number of server requests that are necessary to render a web asset, such as a web page. CSS、JavaScript などの具体的には、任意の数の個別のバンドルを作成できます。少ないファイルでは、サーバーにブラウザーまたはアプリケーションを提供するサービスから HTTP の要求が減少を意味します。You can create any number of individual bundles specifically for CSS, JavaScript, etc. Fewer files means fewer HTTP requests from the browser to the server or from the service providing your application. この結果には、最初のページ読み込みのパフォーマンスが向上しました。This results in improved first page load performance.

縮小Minification

縮小では、機能を変更することがなく、コードから不要な文字を削除します。Minification removes unnecessary characters from code without altering functionality. 要求されたアセット (CSS、画像、JavaScript ファイルなど) に大きなサイズの削減になります。The result is a significant size reduction in requested assets (such as CSS, images, and JavaScript files). 縮小の一般的な副作用は、1 つの文字を変数名を短く、コメントや不要な空白文字を削除するなどがあります。Common side effects of minification include shortening variable names to one character and removing comments and unnecessary whitespace.

次の JavaScript 関数を検討してください。Consider the following JavaScript function:

AddAltToImg = function (imageTagAndImageID, imageContext) {
    ///<signature>
    ///<summary> Adds an alt tab to the image
    // </summary>
    //<param name="imgElement" type="String">The image selector.</param>
    //<param name="ContextForImage" type="String">The image context.</param>
    ///</signature>
    var imageElement = $(imageTagAndImageID, imageContext);
    imageElement.attr('alt', imageElement.attr('id').replace(/ID/, ''));
}

縮小では、次に関数を削減します。Minification reduces the function to the following:

AddAltToImg=function(t,a){var r=$(t,a);r.attr("alt",r.attr("id").replace(/ID/,""))};

だけでなく、コメントと不要な空白文字を削除するには、次のパラメーターと変数名が名前を変更されました。In addition to removing the comments and unnecessary whitespace, the following parameter and variable names were renamed as follows:

Original 名前の変更Renamed
imageTagAndImageID t
imageContext a
imageElement r

バンドルと縮小の影響Impact of bundling and minification

次の表では、個別に資産の読み込みとバンドルと縮小を使用して違いを示します。The following table outlines differences between individually loading assets and using bundling and minification:

アクションAction B/mWith B/M B/分なしWithout B/M 変更Change
ファイルの要求File Requests 77 1818 157%157%
サポート技術情報の転送KB Transferred 156156 264.68264.68 70%70%
読み込み時間 (ミリ秒)Load Time (ms) 885885 23602360 167%167%

ブラウザーは HTTP 要求ヘッダーに関して非常に冗長です。Browsers are fairly verbose with regard to HTTP request headers. 合計バイト数では、バンドルときに、メトリックが大幅に削減を見たを送信します。The total bytes sent metric saw a significant reduction when bundling. ただし、この例をローカルで実行、読み込み時間が大幅に向上を示します。The load time shows a significant improvement, however this example ran locally. アセットをバンドルと縮小を使用して、ネットワーク経由で転送されたときに、大きなパフォーマンスの向上が実現されます。Greater performance gains are realized when using bundling and minification with assets transferred over a network.

バンドルと縮小の戦略を選択します。Choose a bundling and minification strategy

MVC と Razor ページ プロジェクト テンプレートは、バンドルと縮小の JSON 構成ファイルで構成されるため、ボックスのソリューションを提供します。The MVC and Razor Pages project templates provide an out-of-the-box solution for bundling and minification consisting of a JSON configuration file. サード パーティ製ツールなど、 GulpGruntランナーをタスクで、もう少し複雑さで同じタスクを実行します。Third-party tools, such as the Gulp and Grunt task runners, accomplish the same tasks with a bit more complexity. 開発ワークフローにはバンドルと縮小を超える処理が必要な場合、サード パーティのツールは非常によく適合—lint 処理と画像の最適化など。A third-party tool is a great fit when your development workflow requires processing beyond bundling and minification—such as linting and image optimization. デザイン時のバンドルと縮小を使用すると、縮小されたファイルは、アプリのデプロイの前に作成されます。By using design-time bundling and minification, the minified files are created prior to the app's deployment. バンドルと縮小を展開する前に、サーバー負荷の軽減の利点を提供します。Bundling and minifying before deployment provides the advantage of reduced server load. ただし、そのデザイン時のバンドルを認識することが重要と縮小はビルド複雑さも増すし、静的ファイルでのみ動作します。However, it's important to recognize that design-time bundling and minification increases build complexity and only works with static files.

バンドルと縮小を構成します。Configure bundling and minification

ASP.NET Core 2.0 以前では、MVC および Razor ページ プロジェクト テンプレートを提供するbundleconfig.json各バンドルするためのオプションを定義する構成ファイル。In ASP.NET Core 2.0 or earlier, the MVC and Razor Pages project templates provide a bundleconfig.json configuration file that defines the options for each bundle:

ASP.NET Core 2.1 以降では、追加、という名前の新しい JSON ファイルbundleconfig.json、Razor ページまたは MVC プロジェクトのルートにします。In ASP.NET Core 2.1 or later, add a new JSON file, named bundleconfig.json, to the MVC or Razor Pages project root. 開始点として、そのファイルに次の JSON を含めます。Include the following JSON in that file as a starting point:

[
  {
    "outputFileName": "wwwroot/css/site.min.css",
    "inputFiles": [
      "wwwroot/css/site.css"
    ]
  },
  {
    "outputFileName": "wwwroot/js/site.min.js",
    "inputFiles": [
      "wwwroot/js/site.js"
    ],
    "minify": {
      "enabled": true,
      "renameLocals": true
    },
    "sourceMap": false
  }
]

Bundleconfig.jsonファイルは、各バンドルするためのオプションを定義します。The bundleconfig.json file defines the options for each bundle. カスタムの JavaScript の前の例では、1 つのバンドルの構成が定義されている (wwwroot/js/site.js) とスタイル シート (wwwroot/css/site.css) ファイル。In the preceding example, a single bundle configuration is defined for the custom JavaScript (wwwroot/js/site.js) and stylesheet (wwwroot/css/site.css) files.

構成オプションは次のとおりです。Configuration options include:

  • outputFileName: 出力するバンドル ファイルの名前。outputFileName: The name of the bundle file to output. 相対パスを含めることができます、 bundleconfig.jsonファイル。Can contain a relative path from the bundleconfig.json file. 必須required
  • inputFiles: 一緒にバンドルするファイルの配列。inputFiles: An array of files to bundle together. これらは、構成ファイルへの相対パスです。These are relative paths to the configuration file. 省略可能な、* が空の出力ファイルに空の値の結果します。optional, *an empty value results in an empty output file. グロビングパターンがサポートされています。globbing patterns are supported.
  • minify: 出力の場合は、縮小オプションを入力します。minify: The minification options for the output type. 省略可能な既定 - minify: { enabled: true }optional, default - minify: { enabled: true }
  • includeInProject: プロジェクト ファイルに生成されたファイルを追加するかどうかを示すフラグです。includeInProject: Flag indicating whether to add generated files to project file. 省略可能な既定値: falseoptional, default - false
  • sourceMap:、バンドルしたファイルのソース マップを生成するかどうかを示すフラグです。sourceMap: Flag indicating whether to generate a source map for the bundled file. 省略可能な既定値: falseoptional, default - false
  • sourceMapRootPath: 生成されたソース マップ ファイルを保存するルート パス。sourceMapRootPath: The root path for storing the generated source map file.

バンドルと縮小のビルド時の実行Build-time execution of bundling and minification

BuildBundlerMinifier NuGet パッケージは、バンドルの実行とビルド時に縮小できるようにします。The BuildBundlerMinifier NuGet package enables the execution of bundling and minification at build time. パッケージを挿入します。 MSBuild ターゲットビルドおよびクリーン時に実行します。The package injects MSBuild Targets which run at build and clean time. Bundleconfig.json定義済みの構成に基づいて、出力ファイルを生成するために、ビルド プロセスによってファイルを分析します。The bundleconfig.json file is analyzed by the build process to produce the output files based on the defined configuration.

注意

BuildBundlerMinifier は、github の Microsoft サポートを提供コミュニティが主導のプロジェクトに属していません。BuildBundlerMinifier belongs to a community-driven project on GitHub for which Microsoft provides no support. 問題を提出する必要がありますここします。Issues should be filed here.

追加、 BuildBundlerMinifierをプロジェクトにパッケージします。Add the BuildBundlerMinifier package to your project.

プロジェクトをビルドします。Build the project. 次の出力ウィンドウに表示されます。The following appears in the Output window:

1>------ Build started: Project: BuildBundlerMinifierApp, Configuration: Debug Any CPU ------
1>
1>Bundler: Begin processing bundleconfig.json
1>  Minified wwwroot/css/site.min.css
1>  Minified wwwroot/js/site.min.js
1>Bundler: Done processing bundleconfig.json
1>BuildBundlerMinifierApp -> C:\BuildBundlerMinifierApp\bin\Debug\netcoreapp2.0\BuildBundlerMinifierApp.dll
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

プロジェクトをクリーンアップします。Clean the project. 次の出力ウィンドウに表示されます。The following appears in the Output window:

1>------ Clean started: Project: BuildBundlerMinifierApp, Configuration: Debug Any CPU ------
1>
1>Bundler: Cleaning output from bundleconfig.json
1>Bundler: Done cleaning output file from bundleconfig.json
========== Clean: 1 succeeded, 0 failed, 0 skipped ==========

バンドルと縮小のアドホック実行Ad hoc execution of bundling and minification

プロジェクトをビルドせずにアドホック単位でバンドルや縮小タスクを実行することになります。It's possible to run the bundling and minification tasks on an ad hoc basis, without building the project. 追加、 BundlerMinifier.Coreをプロジェクトに NuGet パッケージ。Add the BundlerMinifier.Core NuGet package to your project:

<DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.6.362" />

注意

BundlerMinifier.Core は、github の Microsoft サポートを提供コミュニティが主導のプロジェクトに属していません。BundlerMinifier.Core belongs to a community-driven project on GitHub for which Microsoft provides no support. 問題を提出する必要がありますここします。Issues should be filed here.

このパッケージに含める .NET Core CLI の拡張、 dotnet バンドルツール。This package extends the .NET Core CLI to include the dotnet-bundle tool. パッケージ マネージャー コンソール (PMC) ウィンドウ、またはコマンド シェルで、次のコマンドを実行できます。The following command can be executed in the Package Manager Console (PMC) window or in a command shell:

dotnet bundle

重要

NuGet パッケージ マネージャーとして、*.csproj ファイルに依存関係を追加します<PackageReference />ノード。NuGet Package Manager adds dependencies to the *.csproj file as <PackageReference /> nodes. dotnet bundleコマンドが .NET Core CLI を使用して登録されている場合にのみ、<DotNetCliToolReference />ノードが使用されます。The dotnet bundle command is registered with the .NET Core CLI only when a <DotNetCliToolReference /> node is used. 適宜、*.csproj ファイルを変更します。Modify the *.csproj file accordingly.

ファイルをワークフローに追加します。Add files to workflow

例を検討してください。 追加custom.css 、次のようなファイルが追加されます。Consider an example in which an additional custom.css file is added resembling the following:

.about, [role=main], [role=complementary] {
    margin-top: 60px;
}

footer {
    margin-top: 10px;
}

縮小するcustom.cssでバンドルとsite.cssに、 site.min.cssファイルを追加する相対パスbundleconfig.json:To minify custom.css and bundle it with site.css into a site.min.css file, add the relative path to bundleconfig.json:

[
  {
    "outputFileName": "wwwroot/css/site.min.css",
    "inputFiles": [
      "wwwroot/css/site.css",
      "wwwroot/css/custom.css"
    ]
  },
  {
    "outputFileName": "wwwroot/js/site.min.js",
    "inputFiles": [
      "wwwroot/js/site.js"
    ],
    "minify": {
      "enabled": true,
      "renameLocals": true
    },
    "sourceMap": false
  }
]

注意

または、次のグロビング パターンを使用できます。Alternatively, the following globbing pattern could be used:

"inputFiles": ["wwwroot/**/*(*.css|!(*.min.css))"]

このグロビング パターンは、すべての CSS ファイルに一致し、縮小されたファイルのパターンを除外します。This globbing pattern matches all CSS files and excludes the minified file pattern.

アプリケーションをビルドします。Build the application. 開いているsite.min.cssの内容に注意してくださいとcustom.cssがファイルの末尾に追加されます。Open site.min.css and notice the content of custom.css is appended to the end of the file.

環境ベースのバンドルと縮小Environment-based bundling and minification

ベスト プラクティスとして、アプリのバンドルと縮小されたファイルは、運用環境で使用する必要があります。As a best practice, the bundled and minified files of your app should be used in a production environment. 開発中は、元のファイルは、アプリのデバッグを容易のこと。During development, the original files make for easier debugging of the app.

使用して、ページに含めるファイルを指定、環境タグ ヘルパービューで。Specify which files to include in your pages by using the Environment Tag Helper in your views. 環境タグ ヘルパーは、特定の実行時にのみその内容をレンダリング環境します。The Environment Tag Helper only renders its contents when running in specific environments.

environmentで実行する場合、タグが未処理の CSS ファイルをレンダリング、Development環境。The following environment tag renders the unprocessed CSS files when running in the Development environment:

<environment include="Development">
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Development">
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</environment>

environment以外の環境で実行しているときに、タグがバンドルと縮小の CSS ファイルをレンダリングDevelopmentします。The following environment tag renders the bundled and minified CSS files when running in an environment other than Development. たとえばで実行されているProductionまたはStagingこれらのスタイル シートのレンダリングをトリガーします。For example, running in Production or Staging triggers the rendering of these stylesheets:

<environment exclude="Development">
    <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
          asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
          asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
    <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
<environment names="Staging,Production">
    <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
          asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
          asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
    <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>

Gulp から bundleconfig.json を使用します。Consume bundleconfig.json from Gulp

アプリのバンドルと縮小のワークフローに追加の処理が必要とする場合があります。There are cases in which an app's bundling and minification workflow requires additional processing. 例には、イメージの最適化やキャッシュ バスティング、CDN 資産の処理が含まれます。Examples include image optimization, cache busting, and CDN asset processing. これらの要件を満たすためには、Gulp を使用するバンドルと縮小のワークフローに変換できます。To satisfy these requirements, you can convert the bundling and minification workflow to use Gulp.

Bundler & Minifier 拡張機能を使用します。Use the Bundler & Minifier extension

Visual Studio Bundler & Minifier拡張機能は、Gulp への変換を処理します。The Visual Studio Bundler & Minifier extension handles the conversion to Gulp.

注意

Bundler & Minifier 拡張機能は、github の Microsoft サポートを提供しないコミュニティが主導のプロジェクトに属しています。The Bundler & Minifier extension belongs to a community-driven project on GitHub for which Microsoft provides no support. 問題を提出する必要がありますここします。Issues should be filed here.

右クリックし、 bundleconfig.jsonソリューション エクスプ ローラーでファイルおよび選択Bundler & Minifier > Gulp に変換しています.:Right-click the bundleconfig.json file in Solution Explorer and select Bundler & Minifier > Convert To Gulp...:

Gulp をで変換コンテキスト メニュー項目

Gulpfile.jspackage.jsonファイルがプロジェクトに追加されます。The gulpfile.js and package.json files are added to the project. サポートしているnpmで示されているパッケージ、 package.jsonファイルのdevDependenciesセクションがインストールされています。The supporting npm packages listed in the package.json file's devDependencies section are installed.

グローバルの依存関係として Gulp CLI をインストールする PMC ウィンドウで、次のコマンドを実行します。Run the following command in the PMC window to install the Gulp CLI as a global dependency:

npm i -g gulp-cli

Gulpfile.jsファイルの読み取り、 bundleconfig.jsonファイルの入力、出力、および設定します。The gulpfile.js file reads the bundleconfig.json file for the inputs, outputs, and settings.

'use strict';

var gulp = require('gulp'),
    concat = require('gulp-concat'),
    cssmin = require('gulp-cssmin'),
    htmlmin = require('gulp-htmlmin'),
    uglify = require('gulp-uglify'),
    merge = require('merge-stream'),
    del = require('del'),
    bundleconfig = require('./bundleconfig.json');

// Code omitted for brevity

手動で変換します。Convert manually

Visual Studio や Bundler & Minifier 拡張機能を使用できない場合に、手動で変換します。If Visual Studio and/or the Bundler & Minifier extension aren't available, convert manually.

追加、 package.jsonを次のファイルdevDependenciesプロジェクトのルート。Add a package.json file, with the following devDependencies, to the project root:

"devDependencies": {
  "del": "^3.0.0",
  "gulp": "^4.0.0",
  "gulp-concat": "^2.6.1",
  "gulp-cssmin": "^0.2.0",
  "gulp-htmlmin": "^3.0.0",
  "gulp-uglify": "^3.0.0",
  "merge-stream": "^1.0.1"
}

同じレベルで、次のコマンドを実行して、依存関係をインストールpackage.json:Install the dependencies by running the following command at the same level as package.json:

npm i

グローバルの依存関係として Gulp CLI をインストールします。Install the Gulp CLI as a global dependency:

npm i -g gulp-cli

コピー、 gulpfile.jsをプロジェクトのルート以下のファイルします。Copy the gulpfile.js file below to the project root:

'use strict';

var gulp = require('gulp'),
    concat = require('gulp-concat'),
    cssmin = require('gulp-cssmin'),
    htmlmin = require('gulp-htmlmin'),
    uglify = require('gulp-uglify'),
    merge = require('merge-stream'),
    del = require('del'),
    bundleconfig = require('./bundleconfig.json');

const regex = {
    css: /\.css$/,
    html: /\.(html|htm)$/,
    js: /\.js$/
};

gulp.task('min:js',
    () => merge(getBundles(regex.js).map(bundle => {
        return gulp.src(bundle.inputFiles, { base: '.' })
            .pipe(concat(bundle.outputFileName))
            .pipe(uglify())
            .pipe(gulp.dest('.'));
    })));

gulp.task('min:css',
    () => merge(getBundles(regex.css).map(bundle => {
        return gulp.src(bundle.inputFiles, { base: '.' })
            .pipe(concat(bundle.outputFileName))
            .pipe(cssmin())
            .pipe(gulp.dest('.'));
    })));

gulp.task('min:html',
    () => merge(getBundles(regex.html).map(bundle => {
        return gulp.src(bundle.inputFiles, { base: '.' })
            .pipe(concat(bundle.outputFileName))
            .pipe(htmlmin({ collapseWhitespace: true, minifyCSS: true, minifyJS: true }))
            .pipe(gulp.dest('.'));
    })));

gulp.task('min', gulp.series(['min:js', 'min:css', 'min:html']));

gulp.task('clean', () => {
    return del(bundleconfig.map(bundle => bundle.outputFileName));
});

gulp.task('watch', () => {
    getBundles(regex.js).forEach(
        bundle => gulp.watch(bundle.inputFiles, gulp.series(["min:js"])));

    getBundles(regex.css).forEach(
        bundle => gulp.watch(bundle.inputFiles, gulp.series(["min:css"])));

    getBundles(regex.html).forEach(
        bundle => gulp.watch(bundle.inputFiles, gulp.series(['min:html'])));
});

const getBundles = (regexPattern) => {
    return bundleconfig.filter(bundle => {
        return regexPattern.test(bundle.outputFileName);
    });
};

gulp.task('default', gulp.series(['min']));

Gulp タスクの実行Run Gulp tasks

Visual Studio でプロジェクトをビルドする前に、Gulp 縮小タスクをトリガーするには、次のコードを追加MSBuild ターゲット*.csproj ファイルに。To trigger the Gulp minification task before the project builds in Visual Studio, add the following MSBuild Target to the *.csproj file:

<Target Name="MyPreCompileTarget" BeforeTargets="Build">
  <Exec Command="gulp min" />
</Target>

この例で、内で定義されたすべてのタスク、MyPreCompileTargetターゲットを実行する前に、定義済みBuildターゲット。In this example, any tasks defined within the MyPreCompileTarget target run before the predefined Build target. Visual Studio の出力ウィンドウで、次のような出力が表示されます。Output similar to the following appears in Visual Studio's Output window:

1>------ Build started: Project: BuildBundlerMinifierApp, Configuration: Debug Any CPU ------
1>BuildBundlerMinifierApp -> C:\BuildBundlerMinifierApp\bin\Debug\netcoreapp2.0\BuildBundlerMinifierApp.dll
1>[14:17:49] Using gulpfile C:\BuildBundlerMinifierApp\gulpfile.js
1>[14:17:49] Starting 'min:js'...
1>[14:17:49] Starting 'min:css'...
1>[14:17:49] Starting 'min:html'...
1>[14:17:49] Finished 'min:js' after 83 ms
1>[14:17:49] Finished 'min:css' after 88 ms
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

または、Visual Studio のタスク ランナー エクスプ ローラーを使用して、Gulp タスクを特定の Visual Studio イベントにバインドすることがあります。Alternatively, Visual Studio's Task Runner Explorer may be used to bind Gulp tasks to specific Visual Studio events. 参照してください既定のタスクを実行している手順については、その作業をします。See Running default tasks for instructions on doing that.

その他の技術情報Additional resources