Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically detect minification failures in ASP.NET MVC bundling

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.

like image 819
andkorsh Avatar asked Sep 07 '25 16:09

andkorsh


1 Answers

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.

like image 140
Renato Lemos Avatar answered Sep 10 '25 13:09

Renato Lemos