asp.net-core.net-corerazorbundling-and-minification

Automatic switching to minified version of static file in ASP.NET Core 6+


According to the documentation available here: https://learn.microsoft.com/en-us/aspnet/core/client-side/bundling-and-minification?view=aspnetcore-9.0#environment-based-bundling-and-minification

The recommendation is to use pair of <environment> statements like this:

<environment include="Development">
  add static files not minified to enable debugging in development
</environment>

<environment exclude="Development">
  add minified version of static files with fallback in production
</environment>

The recommendation also describes how to fallback in case the minified version is missing.

Most importantly, the documentation states that: "ASP.NET Core doesn't provide a native bundling and minification solution."

Question

Is there a library or any way to automate this process without duplicating static file entries?

I'm thinking about writing code like the following:

<link rel="stylesheet" href="URL" 
      asp-use-minified="always/production/none" 
      asp-minified-name="filename.min.css"/>

<script src="URL" 
        asp-use-minified="always/production/none" 
        asp-minified-file="filename.min.js"> 

Where asp-use-minified has default value production and empty asp-minified-file implies using common minified name pattern, for example myFile.css => myFile.min.css.


Solution

  • You could create a taghelper like:

    [HtmlTargetElement("myscript")]
    public class MyScriptTagHelper : TagHelper
    {
    
        public MyScriptTagHelper(IWebHostEnvironment env)
        {
            _env=env;
        }
    
        
        [HtmlAttributeName("src")]
        public string src { get; set; }
    
        [HtmlAttributeName("asp-use-minified")]
        public string environment { get; set; }=Environments.Production;
        
    
        [HtmlAttributeName("asp-minified-file")]
        public string? filename { get; set; } 
    
        private readonly IWebHostEnvironment _env;
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            var index = src.IndexOf(".js");
            var isminified = (src.Substring(index-4, 3)=="min"?true:false);
            // If the logic don't totally match your requirement ,you could replace with your logic
            if (_env.EnvironmentName == environment&&!isminified)
            {
                var minifiedFilename = src.Insert(index, ".min");
                output.TagName = "script";
                if (filename != null)
                {
                    output.Attributes.Add("src", filename);
                }
                else
                {
                    output.Attributes.Add("src", minifiedFilename);
                }
                
            }
            else
            {
                output.TagName = "script";
                output.Attributes.Add("src", src);
            }
        }
    }
    

    use it in a View; <myscript asp-use-minified="Development" src="/lib/bootstrap/dist/js/bootstrap.js" asp-minified-file="newfile.min.js"></myscript>

    When I debug:

    enter image description here

    Result:

    enter image description here

    Update:

     [HtmlTargetElement("script",Attributes ="minify")]
     public class MyScriptTagHelper : TagHelper
     {
    
         public MyScriptTagHelper(IWebHostEnvironment env)
         {
             _env=env;
         }
    
         
         [HtmlAttributeName("src")]
         public string src { get; set; }
    
         [HtmlAttributeName("asp-use-minified")]
         public string environment { get; set; }=Environments.Production;
         
    
         [HtmlAttributeName("asp-minified-file")]
         public string? filename { get; set; } 
    
         private readonly IWebHostEnvironment _env;
         public override void Process(TagHelperContext context, TagHelperOutput output)
         {
             var index = src.IndexOf(".js");
             var isminified = (src.Substring(index-4, 3)=="min"?true:false);
             // If the logic don't totally match your requirement ,you could replace with your logic
             if (_env.EnvironmentName == environment&&!isminified)
             {
                 var minifiedFilename = src.Insert(index, ".min");
                 
                 output.TagName = "script";
                 if (filename != null)
                 {
                     output.Attributes.Add("src", filename);
                 }
                 else
                 {
                     output.Attributes.Add("src", minifiedFilename);
                 }
                 
             }
             else
             {
                 output.TagName = "script";
                 output.Attributes.Add("src", src);
             }
             // remove minify attribute of script tag
             output.Attributes.RemoveAll("minify");
    
    
         }
     }
    

    call

    <script asp-use-minified="Development" src="/lib/bootstrap/dist/js/bootstrap.js" asp-minified-file="newfile.min.js" minify></script> in your view

    don't forget call @addTagHelper *, {yourTaghelperAssemblyName} in _ViewImports.cshtml