# ASP.NET Core Web Optimizer
[](https://ci.appveyor.com/project/madskristensen/weboptimizer)
[](https://nuget.org/packages/LigerShark.WebOptimizer.Core/)
ASP.NET Core middleware for bundling and minification of CSS and JavaScript files at runtime. With full server-side and client-side caching to ensure high performance. No complicated build process and no hassle.
Check out the **[demo website](https://weboptimizer.azurewebsites.net/)** or its **[source code](https://github.com/ligershark/WebOptimizer/tree/master/sample)**.
## Versions
Master is being updated for ```ASP.NET Core 3.0```
For ```ASP.NET Core 2.x```, use the **[2.0 branch.](https://github.com/ligershark/WebOptimizer/tree/2.0)**
## Content
- [How it works](#how-it-works)
- [Install and setup](#install-and-setup)
- [Minification](#minification)
- [Bundling](#bundling)
- [Tag Helpers](#tag-helpers)
- [Cache busting](#cache-busting)
- [Inlining content](#inlining-content)
- [Compiling Scss](#compiling-scss)
- [Options](#options)
- [Custom pipeline](#custom-pipeline)
- [Extend](#extend)
- [Plugins](#plugins)
## How it works
WebOptimizer sets up a pipeline for static files so they can be transformed (minified, bundled, etc.) before sent to the browser. This pipeline is highly flexible and can be used to combine many different transformations to the same files.
For instance, the pipeline for a single .css file could be orchestrated to first goes through minification, then through fingerprinting and finally through image inlining before being sent to the browser.
WebOptimizer makes sure that the pipeline is orchestrated for maximum performance and compatability out of the box, yet at the same time allows for full customization and extensibility.
The pipeline is set up when the ASP.NET web application starts, but no output is being generated until the first time they are requested by the browser. The output is then being stored in memory and served very fast on all subsequent requests. This also means that no output files are being generated on disk.
## Install and setup
Add the NuGet package [LigerShark.WebOptimizer.Core](https://nuget.org/packages/LigerShark.WebOptimizer.Core/) to any ASP.NET Core 2.0 project.
```cmd
dotnet add package LigerShark.WebOptimizer.Core
```
Then in **Startup.cs**, add `app.UseWebOptimizer()` to the `Configure` method anywhere before `app.UseStaticFiles` (if present), like so:
```csharp
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseWebOptimizer(); // WebOptimizer
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
```
That sets up the middleware that handles the requests and transformation of the files.
And finally modify the *ConfigureServices* method by adding a call to `services.AddWebOptimizer()`:
```csharp
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddWebOptimizer(); // WebOptimizer
}
```
The service contains all the configuration used by the middleware and allows your app to interact with it as well.
That's it. You have now enabled automatic CSS and JavaScript minification. No other code changes are needed for enabling this.
Try it by requesting one of your .css or .js files in the browser and see if it has been minified.
**Disabling minification:**
If you want to disable minification (e.g. in development), the following overload for AddWebOptimizer() can be used:
```csharp
if (env.IsDevelopment())
{
services.AddWebOptimizer(minifyJavaScript:false,minifyCss:false);
}
```
## Minification
To control the minification in more detail, we must interact with the pipeline that manipulates the file content.
> Minification is the process of removing all unnecessary characters from source code without changing its functionality in order to make it as small as possible.
For example, perhaps we only want a few certain JavaScript files to be minified automatically. Then we would write something like this:
```csharp
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddWebOptimizer(pipeline =>
{
pipeline.MinifyJsFiles("js/a.js", "js/b.js", "js/c.js");
});
}
```
Notice that the paths to the .js files are relative to the wwwroot folder.
We can do the same for CSS, but this time we're using a globbing pattern to allow minification for all .css files in a particular folder and its sub folders:
```csharp
pipeline.MinifyCssFiles("css/**/*.css");
```
When using globbing patterns, you still request the .css files on their relative path such as `http://localhost:1234/css/site.css`.
Setting up automatic minification like this doesn't require any other code changes in your web application to work.
> Under the hood, WebOptimizer uses [NUglify](https://github.com/xoofx/NUglify) to minify JavaScript and CSS.
## Bundling
To bundle multiple source file into a single output file couldn't be easier.
> Bundling is the process of taking multiple source files and combining them into a single output file. All CSS and JavaScript bundles are also being automatically minified.
Let's imagine we wanted to bundle `/css/a.css` and `/css/b.css` into a single output file and we want that output file to be located at `http://localhost/css/bundle.css`.
Then we would call the `AddCssBundle` method:
```csharp
services.AddWebOptimizer(pipeline =>
{
pipeline.AddCssBundle("/css/bundle.css", "css/a.css", "css/b.css");
});
```
The `AddCssBundle` method will combine the two source files in the order they are listed and then minify the resulting output file. The output file `/css/bundle.css` is created and kept in memory and not as a file on disk.
To bundle all files from a particular folder, we can use globbing patterns like this:
```csharp
services.AddWebOptimizer(pipeline =>
{
pipeline.AddCssBundle("/css/bundle.css", "css/**/*.css");
});
```
When using bundling, we have to update our `
```
There is a Tag Helper that understands what the `inline` attribute means and handles the inlining automatically.
## Compiling Scss
WebOptimizer can also compile [Scss](http://sass-lang.com/) files into CSS. For that you need to install the `LigerShark.WebOptimizer.Sass` NuGet package and hooking it up is a breeze. Read more on the [WebOptimizer.Sass](https://github.com/ligershark/WebOptimizer.sass) website.
## Options
You can control the options from the appsettings.json file or in code. The following JSON and C# are equivalent:
```json
{
"webOptimizer": {
"enableCaching": true,
"enableMemoryCache": true,
"enableDiskCache": true,
"cacheDirectory": "/var/temp/weboptimizercache",
"enableTagHelperBundling": true,
"cdnUrl": "https://my-cdn.com/",
"allowEmptyBundle": false,
"httpsCompression": "Compress"
}
}
```
```csharp
services.AddWebOptimizer(pipeline =>
{
pipeline.AddCssBundle("/css/bundle.css", "css/*.css");
pipeline.AddJavaScriptBundle("/js/bundle.js", "js/plus.js", "js/minus.js");
},
option =>
{
option.EnableCaching = true;
option.EnableMemoryCache = true;
option.EnableDiskCache = true;
option.CacheDirectory = "/var/temp/weboptimizercache";
option.EnableTagHelperBundling = true;
option.CdnUrl = "https://my-cdn.com/";
option.AllowEmptyBundle = false;
option.HttpsCompression = HttpsCompressionMode.Compress;
});
```
**enableCaching** determines if the `cache-control` HTTP headers should be set and if conditional GET (304) requests should be supported. This could be helpful to disable while in development mode.
Default: **true**
**enableTagHelperBundling** determines if `
```
...will become this:
```html
```
**allowEmptyBundle** determines the behavior when there is no content in source file of a bundle, by default 404 exception will be thrown when the bundle is requested, set to true to get a bundle with empty content instead.
Default: **false**
### Custom pipeline
Read more in the [custom pipeline documentation](https://ligershark.github.io/WebOptimizer/custom-pipeline.html).
### Extend
Extensions can hook up new transformations and consume existing ones.
A good extension to look at is the [WebOptimizer.Sass](https://github.com/ligershark/WebOptimizer.Sass) extension. It demonstrates how to write a processor and how to write extension methods that makes it easy to hook it up to the pipeline.
### Plugins
- [WebOptimizer.TypeScript](https://github.com/ligershark/WebOptimizer.TypeScript) - compiles TypeScript/ES6+/JSX files to JavaScript (ES5)
- [WebOptimizer.Sass](https://github.com/ligershark/WebOptimizer.Sass) - compiles Scss files to CSS
- [WebOptimizer.Less](https://github.com/ligershark/WebOptimizer.Less) - compiles LESS files to CSS
- [WebOptimizer.Dotless](https://github.com/twenzel/WebOptimizer.Dotless) - compiles LESS files to CSS (using [dotless](https://github.com/dotless/dotless) instead of node.js/less).
- [WebOptimizer.AutoPrefixer](https://github.com/ligershark/WebOptimizer.AutoPrefixer) - Adds vendor prefixes to CSS
- [WebOptimizer.Markdown](https://github.com/ligershark/WebOptimizer.Markdown) - compiles markdown files to HTML
- [WebOptimizer.i18n](https://github.com/ligershark/WebOptimizer.i18n) - localization of .js files