Bundling and Minification in ASP.NET MVC (problem with images) 2013 October 04

Bundling is a new feature in ASP.NET 4.5 that makes it easy to combine or bundle multiple files into a single file. You can create CSS, JavaScript and other bundles. Fewer files means fewer HTTP requests and that can improve first page load  performance.  Minification performs a variety of different code optimizations to scripts or css, such as removing unnecessary white space and comments and shortening variable names to one character. You can read more about these techniques in here. Here are a couple of items that are necessary to know about this amazing performance optimization tool:

  1. Make sure to test this feature before you publish your website. For test purposes when you bundle your css or scripts, IIS does not bundle your files together. You have to set the compilation debug attribute to false to enable the feature in production environment. In the web.config file change the settings to the following:

    <system.web> 
        <compilation debug="false" targetFramework="4.5" /> 
    </system.web> 
    
  2. Pay attention to how you are structuring your files. This is specially important in case of css files as they usually contain relative references to other folders of your website. Here is the default code that bundles jquery UI css files:

    bundles.Add(new StyleBundle("~/Content/themes/base/css")
                    .Include("~/Content/themes/base/jquery.ui.core.css",
                             "~/Content/themes/base/jquery.ui.resizable.css",
                             "~/Content/themes/base/jquery.ui.selectable.css",
                             "~/Content/themes/base/jquery.ui.accordion.css", 
                             "~/Content/themes/base/jquery.ui.autocomplete.css", 
                             "~/Content/themes/base/jquery.ui.button.css", 
                             "~/Content/themes/base/jquery.ui.dialog.css", 
                             "~/Content/themes/base/jquery.ui.slider.css", 
                             "~/Content/themes/base/jquery.ui.tabs.css", 
                             "~/Content/themes/base/jquery.ui.datepicker.css", 
                             "~/Content/themes/base/jquery.ui.progressbar.css", 
                             "~/Content/themes/base/jquery.ui.theme.css")); 
    

    Put a jquery ui element (e.g., an icon) in your html mark up and then look at the resources which are retrieved from the server:

    <span class="ui-icon ui-icon-arrowthick-1-n"></span> 
    

    You will notice that the icon is being loaded from "/Content/themes/base/images/ui-icons_222222_256x240.png". We defined the bundle using "new StyleBundle("~/Content/themes/base/css")". Therefore, all the relative image addresses will start from "~/Content/themes/base" (NOT "~/Content/themes/base**/css**"). Notice that the "images" folder is under the "base" folder. let's see what happens If we try to do a slight modification and shorten the folder address:

    new StyleBundle("~/Content/themes/css")
    

    Notice that while the css files are bundled and minified successfully, the image address has been relatively changed to "/Content/themes/images/ui-icons_222222_256x240.png". Obviously since there is no such file, we are no longer able to see the image. Therefore it is highly recommended to have the complete folder path when we are defining our StyleBundle. Let's look  at another example (which actually motivated me to write this post). It is pretty common for designers to user a folder structure like the following . when they are designing a template:

    • assets
      • css: folder containing stylesheet files
      • img: folder containing images
      • js: folder containing script files

    To define an StyleBundle for this file structure we should write:

    bundles.Add(new StyleBundle("~/Content/assets/css/css")
                    .Include("~/Content/assets/css/reset.css", 
                             "~/Content/assets/css/style.css", 
                             "~/Content/assets/css/colors.css", 
                             ... )); 
    

    If you instead define your bundle path like "StyleBundle("~/Content/css")" You won't be able to see the images.

  3. If you have a hard time working with the default bundling and minification system, there are other alternatives such as Cassette .