Bundling and Minification in ASP.NET Core MVC

Bundling and Minification in ASP.NET Core MVC

In this article, I will discuss Bundling and Minification in ASP.NET Core MVC Applications with Examples. Please read our previous article discussing ASP.NET Core MVC with EF Core DB First Approach with Examples.

Bundling and Minification in ASP.NET Core MVC

Bundling and minification are two important techniques in ASP.NET Core MVC that improve web application performance. These techniques primarily reduce the number of server requests and the size of the requested assets (like CSS, JavaScript, etc.), making web pages load faster.

What is Bundling in ASP.NET Core MVC?

Bundling in ASP.NET Core MVC combines multiple CSS and JavaScript files into a single file. The primary purpose of bundling is to reduce the number of HTTP requests the browser makes to the server, enhancing page load performance. Bundling is essential for optimizing web applications, especially when multiple static files are involved. By consolidating these files, web applications become faster and more efficient.

Fewer requests typically result in faster page-load times because each request introduces overhead in the network communication between the browser (client) and the server. Bundling can improve user experience, especially on high-traffic websites or when dealing with large projects that include numerous CSS or JavaScript files.

Key Benefits of Bundling:
  • Fewer HTTP Requests: Instead of requesting multiple files individually, the browser requests one bundled file, reducing overhead.
  • Improved Performance: With fewer requests, the server’s load decreases, reducing page load times.
What is Minification in ASP.NET Core MVC?

Minification removes all unnecessary characters (such as whitespace, comments, line breaks, newline characters, and sometimes even shortening variable names) from CSS and JavaScript files without changing their functionality. The main objective is to produce a smaller file size, leading to faster downloads and improved performance. Minified files are often difficult to read, so developers typically use non-minified versions during development for easier debugging and use minified versions for production to boost performance.

Key Benefits of Minification:
  • Reduces File Size: Smaller CSS and JavaScript files mean faster downloads for the client.
  • Enhanced Performance: With less data to transfer, the server can respond more quickly, improving page load times. Minimizes bandwidth usage, which is especially beneficial for mobile devices and slower networks.
  • Preserves Functionality: Minified files behave the same way as their non-minified versions, ensuring no loss of functionality.
Example to Understand Bundling and Minification in ASP.NET Core MVC:

First, create an ASP.NET Core Web Application using the Model View Controller Project template and name it BundlingMinificationDemo. Once you have created the project, then please add a few CSS and JavaScript files within css and js folder of your wwwroot folder, as shown in the below image:

Example to Understand Bundling and Minification in ASP.NET Core MVC

Add the following files:
  • CSS: Site.css, StyleSheet2.css, MyStyleSheet.css
  • JS: Site.js, JavaScript2.js, MyJavaScript.js

Now, let us add some dummy content to the above CSS and JS files. Don’t go with the content; just copy and paste it into the respective files. This is just for the demo purpose.

Site.css:
html {
  font-size: 14px;
}

@media (min-width: 768px) {
  html {
    font-size: 16px;
  }
}

html {
  position: relative;
  min-height: 100%;
}

body {
  margin-bottom: 60px;
}
StyleSheet2.css
/* Section styles */
section {
    padding: 20px;
    margin: 20px 0;
}

/* Classes for buttons */
.btn {
    display: inline-block;
    background: #555;
    color: #fff;
    padding: 10px 15px;
    margin: 5px 0;
    text-decoration: none;
    border-radius: 5px;
    transition: background 0.3s;
}
MyStyleSheet.css
/* Basic reset */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: Arial, sans-serif;
    line-height: 1.6;
    color: #333;
    background-color: #f4f4f4;
}

/* Header styles */
header {
    background: #333;
    color: #fff;
    padding: 1rem 0;
    text-align: center;
}
Site.js
// Function to change the background color of the body
function changeBackgroundColor(color) {
    document.body.style.backgroundColor = color;
}

// Function to display a welcome message
function displayWelcomeMessage() {
    alert('Welcome to the dummy JavaScript test!');
}
JavaScript2.js
// Function to calculate and display the sum of two numbers
function calculateSum() {
    var num1 = parseInt(document.getElementById('num1').value, 10);
    var num2 = parseInt(document.getElementById('num2').value, 10);
    var sum = num1 + num2;
    document.getElementById('sumResult').innerText = 'Sum: ' + sum;
}
MyJavaScript.js
// Toggle visibility of an element
function toggleVisibility(elementId) {
    var element = document.getElementById(elementId);
    if (element.style.display === 'none') {
        element.style.display = 'block';
    } else {
        element.style.display = 'none';
    }
}
Using the above CSS and JS Files in our Views:

Suppose we want to use the above CSS and JS files in our view. Then, we can include them in the respective views. But as we will use these files in all our views, it is better and advisable to reference these files in the _Layout.cshtml file. So, please modify the _Layout.cshtml file as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - BundlingMinificationDemo</title>
    <link href="~/css/site.css" rel="stylesheet" />
    <link href="~/css/mystylesheet.css" rel="stylesheet" />
    <link href="~/css/stylesheet2.css" rel="stylesheet" />

    <script src="~/js/javascript2.js"></script>
    <script src="~/js/myjavascript.js"></script>
    <script src="~/js/site.js"></script>

    <link href="~/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Run and Test the Application:

Now, run the application and verify the Network tab. You will see that the client (i.e., browser) issues 6 different requests to the server to load the six files (3 CSS Files and 2 JS Files), as shown in the image below.

Bundling and Minification in ASP.NET Core MVC

The point that you need to remember is that each request will take some time. The more requests between client and server, the more time it will take to load the page. We can overcome this problem and improve the page loading time by using the concept of Bundling and Minification in an ASP.NET Core MVC Application. Let us proceed and see how we can implement bundling and Minification in our ASP.NET Core MVC Application.

How Do We Implement Bundling in ASP.NET Core MVC?

The following is a general approach to implement bundling in ASP.NET Core MVC Application:

  • Use a Build Tool or Package: We can use the BuildBundlerMinifier NuGet package or WebOptimizer to automate bundling.
  • Create/Configure a Bundle Configuration: Provide a configuration (e.g., bundleconfig.json or setup code in Program.cs if using WebOptimizer) that lists input files and specifies the output (bundled) file.
  • Reference the Bundled Output File: Instead of referencing multiple CSS or JS files individually in Razor views or _Layout.cshtml, reference the single bundled file.

Note: Bundling is typically done only for production. In development, keep them separated to simplify debugging.

How Do We Implement Minification in ASP.NET Core MVC?

Minification is generally enabled through the same tools or packages that handle bundling in ASP.NET Core MVC Applications. For example:

  • BuildBundlerMinifier: You can enable minification in the bundleconfig.json file by setting “minify”: {“enabled”: true} for each bundle.
  • WebOptimizer: You can call methods like pipeline.MinifyCssFiles() or pipeline.MinifyJsFiles() in your configuration code in Program.cs.

Note: Once minification is configured, build or run your project. The respective tools will generate the minified output (e.g., .min.css or .min.js files). Always verify that the generated minified file is loaded in your pages (check via browser DevTools → Network tab).

Implementing Bundling and Minification in ASP.NET Core MVC:

First, let us see how to implement Bundling and Minification using the BuildBundlerMinifier package. Then, we will see how to Implement the same using the WebOptimizer package in our ASP.NET Core MVC Application.

Installing BuildBundlerMinifier Package

You can install this BuildBundlerMinifier package via the NuGet Package Manager Console by executing the following command:

  • Install-Package BuildBundlerMinifier

Once you install the above package, it should be visible in the Packages folder under the dependencies section, as shown in the image below.

Implementing Bundling and Minification in ASP.NET Core MVC

Note: Please ensure to enable serving static files middleware (app.UseStaticFiles();) must be registered into the application processing pipeline. When we create the project using the Model View Controller template, it is added to the pipeline by default.

Create a Bundle Configuration File

Create a file named bundleconfig.json in the root of your project. This file defines the bundling and minification settings when we used the BuildBundlerMinifier package.

[
  {
    "outputFileName": "wwwroot/js/MySite.min.js",
    "inputFiles": [
      "wwwroot/js/site.js",
      "wwwroot/js/MyJavaScript.js",
      "wwwroot/js/JavaScript2.js"
    ],
    "minify": {
      "enabled": true,
      "renameLocals": true
    },
    "includeInProject": true
  },
  {
    "outputFileName": "wwwroot/css/MySite.min.css",
    "inputFiles": [
      "wwwroot/css/site.css",
      "wwwroot/css/MyStyleSheet.css",
      "wwwroot/css/StyleSheet2.css"
    ],
    "minify": {
      "enabled": true,
      "renameLocals": true
    },
    "includeInProject": false
  }
]
Configuration Explanations:
  • “outputFileName”: Where the combined and minified file will be placed.
  • “inputFiles”: An array of paths to the original files you want to bundle.
  • “minify”: Configuration object to enable or disable minification and optionally rename local variables.
  • “includeInProject”: If true, the output file is automatically added to your project structure.
Using Wildcards:

You can also use wildcards (“wwwroot/js/*.js”) to bundle all JS files in a folder. That means, instead of specifying the individual input file names, we can use the * as shown below:

[
  {
    "outputFileName": "wwwroot/js/MySite.min.js",
    "inputFiles": [
      "wwwroot/js/*.js"
    ],
    "minify": {
      "enabled": true,
      "renameLocals": true
    },
    "includeInProject": true
  },
  {
    "outputFileName": "wwwroot/css/MySite.min.css",
    "inputFiles": [
      "wwwroot/css/*.css"
    ],
    "minify": {
      "enabled": true,
      "renameLocals": true
    },
    "includeInProject": false
  }
]
Build the Project:

BuildBundlerMinifier processes the bundleconfig.json and generates output files (e.g., MySite.min.js and MySite.min.css) when you build the solution. Once you build the project or solution, you will see the respective files are created in the specified locations, as shown in the below image:

How Do We Implement Bundling in ASP.NET Core MVC?

Reference Bundled Files in Views

In the _Layout.cshtml or any view file, replace the multiple references with the bundled references. So, please modify the _Layout.cshtml file as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - BundlingMinificationDemo</title>
    <link href="~/css/mysite.min.css" rel="stylesheet" />
    <script src="~/js/mysite.min.js"></script>

    <link href="~/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

Now, run the application, and you will see that the browser now makes only 2 requests (1 for CSS, 1 for JS) instead of 6, as shown in the image below.

How Do We Implement Minification in ASP.NET Core MVC?

Note: Implementing minification will definitely improve the application’s performance by reducing the number of requests between the client and server and the file size.

Environment-Based Bundling and Minification

As a best practice, the bundled and minified files should be used in a production environment. During development, the original files make for easier debugging. Use the Environment Tag Helper to load different files based on the current environment. So, basically, in the Development environment, we will load the original and non-minified versions, and in the Production environment, we will load the bundled and minified versions. So, please modify the _Layout.cshtml file as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - BundlingMinificationDemo</title>
    <environment include="Development">
        <link href="~/css/site.css" rel="stylesheet" />
        <link href="~/css/mystylesheet.css" rel="stylesheet" />
        <link href="~/css/stylesheet2.css" rel="stylesheet" />

        <script src="~/js/javascript2.js"></script>
        <script src="~/js/myjavascript.js"></script>
        <script src="~/js/site.js"></script>
    </environment>
    <environment exclude="Development">
        <link href="~/css/mysite.min.css" rel="stylesheet" />
        <script src="~/js/mysite.min.js"></script>
    </environment>

    <link href="~/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Bundling and Minification Using WebOptimizer in ASP.NET Core MVC

WebOptimizer is a middleware component that allows us to bundle and minify CSS and JavaScript files. First, let us install the WebOptimizer NuGet package. You can do this via the NuGet Package Manager or by running the following command in your package manager console:

  • Install-Package LigerShark.WebOptimizer.Core

Note: For clarity, please remove or delete the BuildBundlerMinifier package and bundleconfig.json, the two minified files generated by the BuildBundlerMinifier approach.

Configure WebOptimizer Service and Middleware Component

In the Program.cs file, we need to configure the WebOptimizer service and Middleware component to the request processing pipeline. So, please modify the Program class as follows:

namespace BundlingMinificationDemo
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.
            builder.Services.AddControllersWithViews();

            // Add WebOptimizer services
            // Allows configuration of CSS/ JS bundles.
            builder.Services.AddWebOptimizer(pipeline =>
            {
                // AddCssBundle & AddJavaScriptBundle: Creates bundles and specifies the output location and input files.
                // Bundle CSS
                pipeline.AddCssBundle("/css/bundle.css", "css/site.css", "css/StyleSheet2.css", "css/MyStyleSheet.css");

                // Bundle JS
                pipeline.AddJavaScriptBundle("/js/bundle.js", "js/site.js", "js/JavaScript2.js", "js/MyJavaScript.js");

                // Minify 
                pipeline.MinifyCssFiles();
                pipeline.MinifyJsFiles();
            });

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();

            // Use WebOptimizer before static files
            app.UseWebOptimizer();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");

            app.Run();
        }
    }
}
Modifying the Layout Page

In _Layout.cshtml, replace multiple file references with the bundled ones. So, please modify the _Layout.cshtml file as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - BundlingMinificationDemo</title>
    <link rel="stylesheet" href="~/css/bundle.css">
    <script src="~/js/bundle.js"></script>

    <link href="~/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Run and Test the Application

Run your application and check that the bundled and minified files are being served correctly. You can inspect the network traffic in your browser’s developer tools to confirm that bundle.css and bundle.js are loaded, as shown in the below image:

Bundling and Minification Using WebOptimizer in ASP.NET Core MVC

Note: WebOptimizer dynamically serves bundled files from the /css/bundle.css route. Unlike BuildBundlerMinifier, which physically stores files in a folder, WebOptimizer handles everything in memory, ensuring no direct file creation.

Using Wildcard:

We can use the wildcard to include all CSS or JS files in a folder. For a better understanding, please modify the Program class as follows. In the below code, CSS files located in the css folder and JavaScript files located in the js folder are bundled and minified. The /*.css and /*.js patterns mean “all CSS/JS files in these directories and their subdirectories.”

namespace BundlingMinificationDemo
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.
            builder.Services.AddControllersWithViews();

            // Add WebOptimizer services
            // Allows configuration of CSS/ JS bundles.
            builder.Services.AddWebOptimizer(pipeline =>
            {
                // Using wildcard for CSS files in the "css" folder
                pipeline.AddCssBundle("/css/bundle.css", "css/*.css");

                // Using wildcard for JS files in the "js" folder
                pipeline.AddJavaScriptBundle("/js/bundle.js", "js/*.js");

                // Minify 
                pipeline.MinifyCssFiles();
                pipeline.MinifyJsFiles();
            });

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();

            // Use WebOptimizer before static files
            app.UseWebOptimizer();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");

            app.Run();
        }
    }
}
When and Why Should Bundling and Minification Be Used in ASP.NET Core MVC?

Bundling and minification in ASP.NET Core MVC are essential techniques for creating high-performance, scalable, and efficient web applications. Implement them thoughtfully to enhance user experience and application speed.

Production Environments
  • When: It is always recommended for Production builds to reduce file sizes and the number of requests.
  • Why: Ensures faster load times and better user experience in real-world usage.
Large Projects with Many Files
  • When: When you have multiple CSS and JavaScript files in your project.
  • Why: Bundling combines these into fewer files, dramatically lowering HTTP requests and overhead.
High Traffic Websites
  • When: Sites expecting large volumes of daily traffic.
  • Why: Reduces server load and bandwidth consumption, improving scalability and performance.
Mobile-Friendly Sites
  • When: When targeting users on mobile devices with slower connections.
  • Why: Minified, bundled files load faster on limited bandwidth.

By implementing bundling and minification in ASP.NET Core MVC application using either BuildBundlerMinifier or WebOptimizer, we reduce the number of HTTP requests and the size of CSS and JS files. This results in faster load times, reduced bandwidth usage, and an overall smoother user experience. Always use environment-based configurations to keep debugging simple during development (use unbundled, non-minified files) while production benefits from optimized performance (use bundled, minified files).

In the next article, I will discuss How to Host the ASP.NET Core Web Application Into an IIS Server with Examples. In this article, I try to explain Bundling and Minification in ASP.NET Core MVC Applications with Examples. I hope you enjoy this article on Bundling and Minification in ASP.NET Core MVC.

Leave a Reply

Your email address will not be published. Required fields are marked *