Scott Hanselman

WebOptimizer - a Bundler and Minifier for ASP.NET Core

November 08, 2017 Comment on this post [12] Posted in ASP.NET | DotNetCore | Open Source
Sponsored By

ASP.NET Core didn't have a runtime bundler like previous versions of ASP.NET. This was a bummer as I was a fan. Fortunately Mads Kristensen created one and put it on GitHub, called WebOptimizer.

WebOptimizer - 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.

I'll try it out on a default ASP.NET Core 2.0 app.

First, assuming I've installed http://dot.net I'll run

C:\Users\scott\Desktop> cd squishyweb

C:\Users\scott\Desktop\squishyweb> dotnet new mvc
The template "ASP.NET Core Web App (Model-View-Controller)" was created successfully.
This template contains technologies from parties other than Microsoft, see https://aka.ms/template-3pn for details.

SNIP

Restore succeeded.

Then I'll add a reference to the WebOptimizer package. Be sure to check the versioning and pick the one you want, or use the latest.

C:\Users\scott\Desktop\squishyweb> dotnet add package LigerShark.WebOptimizer.Core --version 1.0.178-beta 

Add the service in ConfigureServices and add it (I'll do it conditionally, only when in Production) in Configure. Notice I had to put it before UseStaticFiles() because I want it to get the first chance at those requests.

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddWebOptimizer();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseWebOptimizer();
app.UseExceptionHandler("/Home/Error");
}

app.UseStaticFiles();

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}

After running "dotnet run" I'll request site.css as an example and see it's automatically minimized:

CSS minification automatically

You can control the pipeline with globbing like this:

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddWebOptimizer(pipeline =>
{
pipeline.MinifyJsFiles("js/a.js", "js/b.js", "js/c.js");
});
}

If I wanted to combine some files into an output "file" that'll be held/cached only in memory, I can do that also. To be clear, it'll never touch the disk, it's just a URL. Then I can just refer to it with a <link> within my Razor Page or main Layout.

services.AddWebOptimizer(pipeline =>
{
pipeline.AddCssBundle("/css/mybundle.css", "css/*.css");
});

WebOptimizer also supports automatic "cache busting" with a ?v= query string created by a TagHelper. It can even compile Scss (Sass) files into CSS. There's plugins for TypeScript, Less, and Markdown too!

WebOptimizer is open source and lives at https://github.com/ligershark/WebOptimizer. Go check it out, kick the tires, and see if it meets your needs! Maybe get involved and make a fix or help with docs! There are already some open issues you could start helping with.


Sponsor: Check out JetBrains Rider: a new cross-platform .NET IDE. Edit, refactor, test and debug ASP.NET, .NET Framework, .NET Core, Xamarin or Unity applications. Learn more and download a 30-day trial!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service
November 08, 2017 13:49
Nice - just in time for my first dotnetcore single page app project, too.
November 08, 2017 14:25
This looks super useful, especially for folks who are either just starting out or haven't mastered the absolute wizardry of WebPack (or are using a template which doesn't include WebPack).

What would take this to the next level is if a developer could supply a config for it (as a json/ini/xml) and load that in. At least, in my opinion.
November 08, 2017 14:59
Smidge has been around as a runtime bundler since the beginning of ASP.NET Core even back when DNX, etc... was a thing

https://github.com/shazwazza/smidge


November 08, 2017 15:30
Wouldn't it be better to bunble/minify files at release/publish time? In my opinion thats wasted CPU/Memory to bundle/minify them at runtime.
November 08, 2017 16:50

Wouldn't it be better to bunble/minify files at release/publish time?

Sure but you could use your favourite production checks obviously to resolve that (#ifdef !DEBUG)
November 08, 2017 18:57
If I understand this correctly, this removes my pain. No more Node JS to get NPM to get Bower to install bootstrap or jquery. Just drop the js and css in folders again. Use the taghelpers to use cdn in production and use weboptimizer for my own js and sass to minimize, combine etc.
November 08, 2017 19:27
It would be nice it if flattened out the HTML, the JS mostly comes minified already from bower so, what is the point?
November 08, 2017 21:06
Why not use the "Bundler & Minifier" VS extension also by Mads?
November 08, 2017 22:01
It would be nice it if flattened out the HTML, the JS mostly comes minified already from bower so, what is the point?
November 11, 2017 19:03
Why not use the "Bundler & Minifier" VS extension also by Mads?
Yeah I was wondering the same thing.
November 15, 2017 17:35
I like this syntax very much. Thanks for sharing.
November 19, 2017 14:37
Extending on Scott's description, find all minification information required for front-end minification, at compile time, for Gradle :-

Gradle JS and CSS Minification Tasks

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.