ASP.NET MVC built it minification does not support all CSS features

By Mirek on (tags: ASP.NET, Bundling, css, Minification, categories: architecture, code, web)

Recently I stumbled upon a problem that a CSS file was not minified on production in my ASP.NET MVC 5 web application. Moreover the error saying “Minification failed. Returning unminified contents.” was added to the CSS content. It turned out that it’s an old, known issue and in this post I will show you how I fixed it.

Issue was known, but not really severe, because it was related to quite specific circumstances. When you decide not to use any style preprocessors like LESS or SASS, all you need to do in ASP.NET MVC application is to add a css file and inform the framework to bundle and minify it on application start, like usuall:

bundles.Add(new StyleBundle("~/Content/site-css")
.Include("~/Content/css-reset.css")
.Include("~/Content/site.css"));

But the assembly Microsoft.AspNet.Web.Optimization containing the StyleBundle class, which is responsible for bundling and minification, was not updated since 2014. Now when you use some latest features of CSS like css variables, you will get a non minified content on production with some additional error message attached to it. The error message clearly says it couldn’t handle the css variable syntax. There are also known problems with import syntax as well.

/* Minification failed. Returning unminified contents.
(8,5): run-time error CSS1062: Expected semicolon or closing curly-brace, found '-'
(17,28): run-time error CSS1039: Token not allowed after unary operator: '-color-background'
*/

Now, to make it working we have to skip the default bundling and minification and use some third party. Let’s use the solution that is recommended for ASP.NET Core 3.1 web applications as described in the docs here.

First we need to install the BuildBundlerMinifier package, which adds a special build targets and will perform the bundling and minification during the project build.

Next we need to add the bundleconfig.json file to the application project and configure the file to be processed as follows

[{
"outputFileName": "Content/site.min.css",
"inputFiles": [
"Content/css-reset.css",
"Content/site.css"
]
}]

Having that in place we can now build the project and see if we get all css content minified into one css file site.min.css.

Once we get that we need to simply link the minified file in our html content

<link href="Content/site.min.css" rel="stylesheet">

And we are done.
Unfortunatelly we dont have a support for development mode where we could have the unminified version of css file to easilly work on. In ASP.NET Core there are environmantal variables which can be used to conditionally link the minified or unminified version of the file. Let’s try to mimick simmilar functionality here in ASP.NET MVC 5 application.

First we need some flag that will tell us if we are in development or not. LEts use MvcApplication class for that and add a static property which will hold that information forlatter use.

public class MvcApplication : System.Web.HttpApplication
{
public static bool IsDevEnvironment = false;

protected void Application_Start()
{
CheckDevEnvironment();
/*other calls*/
}

[Conditional("DEBUG")]
private void CheckDevEnvironment()
{
IsDevEnvironment = true;
}
}

Now we can easilly check that value in razor page and link unminified version of files during development

@if(MvcApplication.IsDevEnvironment)
{
<link href="~/Content/css-reset.css" rel="stylesheet">
<link href="~/Content/site.css" rel="stylesheet">
}
else
{
<link href="~/Content/site.min.css" rel="stylesheet">
}

That's it!