Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

A library for optimizing and bundling web assets of ASP.NET Core applications.

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE-THIRD-PARTY
NotificationsYou must be signed in to change notification settings

adams85/bundling

Repository files navigation

📣 Important notices
If you use the design-time features of the library, please note that version 3.0 switches to the Global / Local .NET Core CLI extensibility model. See thedocumentation for further information.

This library can be used to bundle and optimize web assets of ASP.NET Core 2+ applications. Primarily, it was developed as a .NET Core replacement for theSystem.Web.Optimization library of classic ASP.NET, which provides these features at run-time. However, starting with version 2.0,webpack-like design-time usage mode is also supported in the form of a .NET Core CLI extension tool.

NuGet ReleaseDonate

Main features

  • CSS minification and bundling including support for CSS pre-processors:
  • JavaScript minification and bundling. Version 2.0 adds support forrewriting and bundling ES6 (ECMAScript 2015) modules (built onAcornima).
  • Straightforward and flexible configuration:
    • Fluent API configuration.
    • Hierarchical configuration system (settings adjustable on general and more detailed levels).
    • Compatibility withbundleconfig.json.
  • Full control over server and client-side caching (including cache busting).Memory andfile system cache implementations are included.
  • Replaceable backing storage by leveraging.NET Core file system abstractions.
  • Automatic refresh of affected bundles on change of input files. As of version 2.0, not only the directly referenced butalso the imported files are watched (in the case of LESS, SASS/SCSS and ES6 module bundles).
  • Razor tag helpers and the familiar,System.Web.Optimization-like API can be used, as well.
  • Correct handling of URL path prefixes (app branch prefix, static files middleware prefix, etc.)
  • Fully customizable transformation pipelines.
  • Dynamic content sources andquery string parameterized bundles.
  • Modular design, extensibility.

Table of Contents

Quick Start

Installation

Run-time mode
1. Register bundling services
2. Define bundles
3. Configure Razor views
4. Reference bundles in Razor views

Design-time mode
1. Define bundles
2. Produce bundles

Reference
a. Bundling middleware settings
b. Bundle settings

Samples

Quick Start

If you want to get a quick overview of the capabilities of the library, check outthis sample project. This is a slightly modified version of theASP.NET Core Web App template of the .NET SDK, so you can even use it as a starting point for your web application projects.

Installation

TheKarambolo.AspNetCore.Bundling package contains the core components and interfaces but no actual implementation. Therefore you need to install additional packages depending on your preferences/requirements.

Minimizer

You can choose between implementations usingNUglify andWebMarkupMin currently:

dotnet add package Karambolo.AspNetCore.Bundling.NUglify

or

dotnet add package Karambolo.AspNetCore.Bundling.WebMarkupMin

CSS pre-processor

If you want to use CSS pre-processor features, you will also need one of the following packages:

  • LESS

    dotnet add package Karambolo.AspNetCore.Bundling.Less
  • SASS/SCSS

    dotnet add package Karambolo.AspNetCore.Bundling.Sass

    Note: The current implementation usesLibSassHost under the hood, which is a wrapper aroundLibSass, an unmanaged library written in C/C++. Therefore you need to install an additional NuGet package which contains this native dependency compiled to your target platform. E.g. on Windows x64 systems:dotnet add package LibSassHost.Native.win-x64. For further details refer to thedocumentation of LibSassHost.

ES6 module bundler

Finally, if you want to bundle ES6 modules, you need to install an additional package:

dotnet add package Karambolo.AspNetCore.Bundling.EcmaScript

Note: ES6 module bundling is built onAcornima, which supportslanguage features up to ECMAScript 2023 currently. If you want to utilize even newer features (or you just want to target an older JavaScript version), you may use TypeScript for down-level compilation. (See theTypeScriptDemo sample.)

Run-time mode

Choosing this method, your bundles are built on-demand during the execution of your application. Of course, the produced bundles are cached so this is a one-time cost only. In return you get some unique features like dynamic bundles which are not possible when building bundles at design-time.

To set up run-time bundling, you need to walk through the following steps:

1. Register bundling services

Add the following to theConfigureServices method of yourStartup class:

services.AddBundling()    .UseDefaults(Environment) // see below    .UseNUglify() // or .UseWebMarkupMin() - whichever minifier you prefer    .AddLess() // to enable LESS support    .AddSass() // to enable SASS/SCSS support    .AddEcmaScript() // to enable support for ES6 modules    .EnableCacheHeader(TimeSpan.FromDays(1)); // to enable client-side caching

TheEnvironment property should return the current hosting environment. You can inject it in the constructor like this:

// In versions older than ASP.NET Core 3, use IHostingEnvironment instead of IWebHostEnvironmentpublic IWebHostEnvironment Environment { get; }public Startup(IConfiguration configuration, IWebHostEnvironment environment){    Configuration = configuration;    Environment = environment;}

UseDefaults adds support for CSS and JavaScript bundles, sets up the default transformations and enables memory caching.

When hosting environment is set toDevelopment,UseDefaults

  • enables change detection (cache invalidation on change of source files) and
  • enables including of source files instead of the actual bundled output (of course, this will apply only to bundles which allow this),

otherwise

  • enables minification.

If you want to switch to file system-backed caching, callUseFileSystemCaching() on the builder (afterUseDefaults).

Besides that, there are some further settings available to tweak on the builder.

2. Define bundles

Bundles are defined in theConfigure method of theStartup class in the following manner:

app.UseBundling(bundles =>{    // loads bundles from a BundlerMinifier config file    bundles.LoadFromConfigFile("/bundleconfig.json", _env.ContentRootFileProvider);    // defines a CSS bundle (you can use globbing patterns to include/exclude files)    bundles.AddCss("/virtual-path/to/bundle.css")        .Include("/physical-path/to/include.css")        .Include("/another/physical-path/to/pattern*.css")        .Exclude("/**/*.min.css");    // defines a LESS bundle (you should include entry point files only)    bundles.AddLess("/virtual-path/to/less-bundle.css")        .Include("/physical-path/to/main.less");    // defines an SCSS bundle (you should include entry point files only)    bundles.AddSass("/virtual-path/to/scss-bundle.css")        .Include("/physical-path/to/main.scss");    // defines a JavaScript bundle    bundles.AddJs("/virtual-path/to/bundle.js")        .Include("/physical-path/to/*.js");        //.EnableEs6ModuleBundling(); - uncomment this line if you want the included files to be treated as ES6 modules (include only entry point file(s) in this case!)});

UseBundling adds a middleware to the ASP.NET Core request pipeline. You can consider it as a static files middleware, so you need to place it after the exception handler middleware but before the MVC middleware (and probably before authentication or authorization middlewares).

The behavior of the middleware can be customized by supplying aBundlingOptions instance to theUseBundling method. Thepossible settings are listed in the Reference section.

By default, the bundle URL paths will be prefixed with/bundles (this can be changed through theRequestPath option though), so the bundle registered to/virtual-path/to/bundle.css will be accessible at~/bundles/virtual-path/to/bundle.css.However, you need to specify prefixed paths when you reference bundles in the Razor views! (Since even multiple bundling middlewares can be registered with different prefixes.)

It's also important toinclude the proper file extension (which corresponds to the outputted content) in the bundle path, otherwise the file won't be served. (Or you may mess with the options and supply anotherIContentTypeProvider, but that would be quite an unusual use case.)

By default, the include (and exclude) file paths are relative to thewwwroot folder (to be precise, to the root path of the file provider specified by theWebRootFileProvider property of the currentIWebHostEnvironment). It's important to keep in mind thatthe file provider abstraction doesn't allow to access files located outside its root path! In such cases you need to create anotherPhysicalFileProvider with the right root path and pass that in by theSourceFileProvider option.

When specifying includes/excludes, you can use the ordinary globbing patternssupported by the .NET Core file providers.

Tip: instead of inefficiently adding excludes to remove some particular (like pre-minified) files, you may consider to implement anIFileBundleSourceFilter and add it as a global file filter.

3. Configure Razor views

In order to enable the bundling tag helpers you need to include the following lines in your_ViewImports.cshtml:

@using Karambolo.AspNetCore.Bundling.ViewHelpers@addTagHelper *, Karambolo.AspNetCore.Bundling

4. Reference bundles in Razor views

Bundles can be referenced by tag helpers and static helper methods as well:

<!DOCTYPE html><html><head>    @* [...] *@    @* references stylesheet bundle using tag helper *@    <link rel="stylesheet" href="~/bundles/virtual-path/to/bundle.css" />    @* references stylesheet bundle using static helper *@    @await Styles.RenderAsync("~/bundles/virtual-path/to/less-bundle.css")</head><body>    @* [...] *@    @* references script bundle using tag helper *@    <script src="~/bundles/virtual-path/to/bundle.js"></script>    @* references script bundle using static helper *@    @await Scripts.RenderAsync("~/bundles/virtual-path/to/bundle.js")</body></html>

Design-time mode

Starting with version 2.0, it's possible to pre-build bundles at design-time. This is similar to howwebpack or Mads Kristensen'sBundlerMinifer works.

Just like in the case of run-time bundling, install the required NuGet packages first. On top of that you need tomake sure that the core library is referenced as well:

dotnet add package Karambolo.AspNetCore.Bundling

(This package contains some files which are necessary to extend the build process and make the design-time method work.)

Prior to version 3.0 the step above automatically enabled the .NET Core CLI extensiondotnet bundle by adding the necessaryDotNetCliToolReference to your project. However,DotNetCliToolReference is more or less obsolete now, so version 3.0 switches tothe newer approach introduced in NET Core 2.1. Thus,from version 3.0 on, you also need to install the .Net Core CLI extension manually. In return, you have multiple options to choose from:

  • You can make the tool globally available on your development machine.

    dotnet tool install -g dotnet-bundlingtools
  • You can install the tool into a specific directory.

    dotnet tool install --tool-path .tools dotnet-bundlingtools
  • You can make the tool available in your project only. (Please note thatLocal Tools are available since .NET Core 3 only.)

    dotnet new tool-manifestdotnet tool install dotnet-bundlingtools

After installing the necessary components, check if everything has been set up correctly: issue thedotnet bundle --version command in your project folder.

1. Define bundles

First you need to describe your bundles, which can be done in two ways currently. (These methods are not exclusive, you can even specify multiple configurations.)

1.a. Defining bundles by configuration file

You may define your bundles by placing abundleconfig.json file in the root folder of your project. Originally, this format was established by Mads Kristensen'sBundlerMinifier library but it is supported here as well. For details, please refer to theoriginal documentation.

1.b. Defining bundles by code

In many cases configuration files are sufficient to define your bundles, but there are some features and settings which are not accessible using this approach. When you need full control over configuration, you have the option to specify it by code. All you need to do is create a class (with a default constructor) inheriting fromDesignTimeBundlingConfiguration in your ASP.NET Core application:

public class MyBundles : DesignTimeBundlingConfiguration{    public MyBundles() { }    // this property should return an enumeration of the used modules    public override IEnumerable<IBundlingModule> Modules => base.Modules // CSS and JavaScript modules are already added by the base class        .Append(new NUglifyBundlingModule()) // or .Append(new WebMarkupMinBundlingModule()) - whichever minifier you prefer        .Append(new LessBundlingModule()) // to enable LESS support        .Append(new SassBundlingModule()) // to enable SASS/SCSS support        .Append(new EcmaScriptBundlingModule()); // to enable support for ES6 modules    // in this method you can define your bundles using fluent API    public override void Configure(BundleCollectionConfigurer bundles)    {        // defines a CSS bundle (you can use globbing patterns to include/exclude files)        bundles.AddCss("/virtual-path/to/bundle.css")            .Include("/physical-path/to/include.css")            .Include("/another/physical-path/to/pattern*.css")            .Exclude("/**/*.min.css");        // defines a LESS bundle (you should include entry point files only)        bundles.AddLess("/virtual-path/to/less-bundle.css")            .Include("/physical-path/to/main.less");        // defines an SCSS bundle (you should include entry point files only)        bundles.AddSass("/virtual-path/to/scss-bundle.css")            .Include("/physical-path/to/main.scss");        // defines a JavaScript bundle        bundles.AddJs("/virtual-path/to/bundle.js")            .Include("/physical-path/to/*.js");        //.EnableEs6ModuleBundling(); - uncomment this line if you want the included files to be treated as ES6 modules (include only entry point file(s) in this case!)    }}

When subclassing the abstractDesignTimeBundlingConfiguration class, you have to provide an implementation for theConfigure method as shown in the example.

You usually need modules other than the core ones (CSS, JavaScript). If so, these modules need to be specified by overriding theModules property.

There are additional properties which you can override to tweak global settings. For details, see theBundle settings reference.

2. Produce bundles

Depending on your workflow, you have the following three options to process the configuration(s) and create the specified bundles:

2.a. Producing bundles manually

Execute thedotnet bundle command in your project folder and that's it.

By default, the CLI tool

  • checks for a configuration file (bundleconfig.json in the project folder) and
  • looks for code configuration in your application as well.

To be able to do the latter, the tool has to build your project first. If you don't use code configuration, you may rather use thedotnet bundle --sources ConfigFile command. This way, the tool skips building your application.

2.b. Updating bundles on build

You can easily setup your application to automatically update your bundles when you build it. Just insert these several lines under the root element (Project) of your project (csproj) file:

<PropertyGroup>  <BundleOnBuild>true</BundleOnBuild></PropertyGroup>

When (re)building your project the next time, you should see the processed bundle configuration(s) in the build output.

Actually, no magic happens under the hood, just the CLI tool is invoked as a part of the build process. Because of that, you can supply the same options as if you executed it manually, you just need to use MSBuild properties:

MSBuild propertyCLI tool option
BundlingConfigSources--sources
BundlingConfigFile--config-file
BundlingMode--mode
2.c. Updating bundles on change of input files

This use case is not supported out-of-the-box currently, but you can make it work by the help of another CLI tool:dotnet watch.

Web assets are not monitored by default, so you need to add something like this to your project file first:

<ItemGroup>  <Watch Include="wwwroot\**\*" Exclude="wwwroot\bundles\**\*;$(DefaultExcludes)"  /></ItemGroup>

(For the exact configuration and capabilities of thewatch tool, please refer toits official documentation.)

Then you can start monitoring by issuing thedotnet watch bundle --no-build command in the project folder.

Reference

a. Bundling middleware settings

The behavior of the bundling middleware can be tweaked by passing aBundlingOptions instance to theUseBundling method.

DescriptionDefault value
SourceFileProviderThe file provider to use to access input files.IWebHostEnvironment.​WebRootFileProvider
CaseSensitiveSourceFilePathsSpecifies if paths to input files should be treated as case-sensitive.false whenSourceFileProvider abstracts a physical file system on Windows, otherwise true
StaticFilesRequestPathThe path prefix to use when doing URL rebasing of other referenced web assets such as images, fonts, etc.none
RequestPathThe path prefix to add to bundle URLs. It may be empty but that is not recommended as in that case identification of non-bundle requests requires some additional steps."/bundles"
ContentTypeProviderUsed to map files to content-types.
DefaultContentTypeThe default content type for a request ifContentTypeProvider cannot determine one.none
ServeUnknownFileTypesSpecifies if files of unrecognized content-type should be served.false
OnPrepareResponseThis can be used to add or change the response headers.

b. Bundle settings

Bundle settings can be configured on multiple levels: globally, per bundle type, per bundle and per bundle item.

Settings made on a higher (more general) level is effective until it's overridden on a lower (more detailed) level. Technically, this means if a property is set to null, the corresponding setting value will be inherited from the higher level (if any). If it's set to a non-null value, the setting will be effective on the current and lower levels.

The configuration levels from high to low:

  1. Global settings

    • In run-time mode, these settings can be configured when registering services using theAddBundling method. You may tweak them by a configuration delegate passed in to the mentioned method. Some of them can be specified using fluent API, as well.

    • In design-time mode, you configure these settings by overriding the corresponding properties of theDesignTimeBundlingConfiguration class.

  2. Per bundle type settings

    • In run-time mode, these settings can be set also using configuration delegates when calling theAddCss,AddJs, etc. extensions methods on the builder returned byAddBundling.

    • In design-time mode, the configuration delegates can be passed to the constructors of modules when overriding theModules property of theDesignTimeBundlingConfiguration class.

  3. Per bundle settings

    If you need more detailed control, you can specify settings for a single bundle using fluent API when defining them inUseBundling /DesignTimeBundlingConfiguration.Configure.

  4. Per bundle item settings

    There are some settings which can even be tweaked for items of bundles. These can be set by the optional parameters of theInclude method available on the builder returned byAddCss,AddJs, etc.

Overview of settings
DescriptionDefault valueGlobalPer typePer bundlePer item
EnableMinificationEnables minification globally. If set to true, minification transformations will be added to the pipeline by default.falseX
EnableChangeDetectionEnables change detection of the source files. On change the cache for the involved bundles will be invalidated.falseX
EnableCacheBustingEnables cache busting. If set to true, a version part will be added to the include URLs. (This global setting can be overrided for individual includes. Look for thebundling-add-version attribute or theaddVersion parameter of the tag helper or static helper methods respectively.)false whenIWebHostEnvironment.​EnvironmentName is equal to "Development", otherwise trueX
EnableCacheHeaderEnables client-side caching. If set to true, the Cache-Control HTTP header will be sent automatically.falseX
CacheHeaderMaxAgeSpecifies the max-age value the Cache-Control HTTP header.undefinedX
EnableSourceIncludesEnables including of source files instead of the actual bundled output. This is useful during development, however it's only possible when the bundle has no substantial transformations (such as pre-processing).falseXXX
SourceItemToUrlMapperUsed to map source items to URLs when rendering source includes.a default mapper which is able to determine URLs of files located within the root directory ofIWebHostEnvironment.​WebRootFileProviderXXX
StaticFileUrlToFileMapperUsed to map URLs to file provider files when file versions for pre-bundled or non-bundle files need to be computed. You only need to consider this option if you want cache busting for such files and those are not accessible at the standard location (e.g. you use some prefix for your static files).a default mapper which maps local URLs to files withinIWebHostEnvironment. WebRootFileProvider.X
BuilderThe object responsible to produce the output of the bundle.XXX
FileFiltersObjects that filters or sorts the input file list provided by file sources.XXX
ItemTransformsTransformations that are applied to each input item. (This can even be set on item level.)XXXX
TransformsTransformations that are applied to the concatenated output of input item transformations.XXX
ConcatenationTokenThe string to use to concatenate the outputs of input item transformations."\n" for Css outputs
";\n" for Js outputs
XX
CacheOptionsOptions for bundle output caching.cache with no expirationX
DependsOnParamsDeclares that the query string is relevant for caching as the bundle use it to provide its output.falseX
OutputEncodingEncoding of the output.UTF-8X
InputEncodingEncoding of the input.auto-detect, fallback to UTF-8X

Samples

If you're new to the library or want to learn more about its capabilities, I suggest looking aroundhere where you find some simple demo applications like:

VueDemo

This sample shows how you can setup a component-based Vue.js application. (This one uses vanilla JavaScript and doesn't use ES6 modules but it can be easily re-configured by examining the setup of theTypeScriptDemo app.)

DynamicBundle

Check outthis demo to get an idea how dynamic parameterized bundles works and what they can be used for.

Any feedback appreciated, contributions are welcome!

About

A library for optimizing and bundling web assets of ASP.NET Core applications.

Resources

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE-THIRD-PARTY

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp