From time to time I notice the following error message on the top of my CSS bundle produced by ASP.NET MVC:
/* Minification failed. Returning unminified contents.
(7933,26): run-time error CSS1019: Unexpected token, found ':'
(7933,26): run-time error CSS1042: Expected function, found ':'
(7933,26): run-time error CSS1062: Expected semicolon or closing curly-brace, found ':'
(7934,30): run-time error CSS1019: Unexpected token, found ':'
(7934,30): run-time error CSS1042: Expected function, found ':'
(7934,30): run-time error CSS1062: Expected semicolon or closing curly-brace, found ':'
*/
These errors always go silently through the build, deployment and unit tests and are very hard to notice. Is there any solution to automatically catch them? It is hard to get that from the unit test as there's no content folder being copied to the unit test project. Preferably this should fail the build or at least unit test.
In a project that does not contain tests, using the James Close answer, I was able to display an alert with the minification failures when loading the system, although it did not cause the compilation to fail, we managed to catch the failures in the development environment:
public static IHtmlString Render(this BundleCollection bundles, string bundleVirtualPath) {
Bundle bundle = bundles.GetBundleFor(bundleVirtualPath);
List<IHtmlString> renderTags = new List<IHtmlString>();
... omitted for simplification
List<string> errors;
if (!bundle.IsValid(out errors)) {
renderTags.Add(new HtmlString($"<script type='text/javascript'>alert('{HttpUtility.JavaScriptStringEncode(string.Join(Environment.NewLine, errors))}');</script>"));
}
return MvcHtmlString.Create(string.Join(Environment.NewLine, renderTags));
}
private static bool IsValid(this Bundle bundle, out List<string> errors) {
errors = new List<string>();
// Get items in included order
BundleContext bundleContext = new BundleContext(new HttpContextWrapper(HttpContext.Current), new BundleCollection(), Guid.NewGuid().ToString());
IEnumerable<BundleFile> bundleFiles = bundle.EnumerateFiles(bundleContext);
bool isStyleBundle = (bundle is StyleBundle);
foreach (BundleFile bundleFile in bundleFiles) {
string physicalPath = HttpContext.Current.Server.MapPath(bundleFile.IncludedVirtualPath),
fileContent = File.ReadAllText(physicalPath);
// Create minifier used by webgrease System.Web.Optimization
var minifier = new Microsoft.Ajax.Utilities.Minifier();
if (isStyleBundle) {
minifier.MinifyStyleSheet(fileContent);
} else {
minifier.MinifyJavaScript(fileContent);
}
// Verify error in minification
if (minifier.Errors.Any()) {
errors.Add($"Minification failed for {bundleFile.IncludedVirtualPath}, errors:{Environment.NewLine}{string.Join(Environment.NewLine, minifier.Errors)}");
}
}
return errors.Any() == false;
}
I hope the above code can help someone in the future.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With