Minify and bundle CSS and JavaScript files in EPiServer 7

Denna artikel har migrerats från en tidigare version av vår webbplats och kan därför avvika i utseende och funktionalitet.

Den här artikeln är inte översatt till svenska och visas därför på engelska istället.


In this post we look at how to use ASP.NET MVC 4 features to minify and bundle CSS and JavaScript files in an EPiServer 7 context.

Uppskattad lästid : 8 minuter

Gå till avsnitt

What is bundling and minification?

Bundling is the process of combining multiple CSS or JavaScript files into one single file, mainly to reduce the number of browser requests.

Minification is the process of sacrificing CSS and JavaScript readability for brevity by shortening variable names, removing spaces and line breaks, etc – all in the name of reducing file size.

Add the optimization package for ASP.NET MVC 4

Before we can use bundling and minification we need to add the ASP.NET Web Optimization Framework NuGet package to our project in Visual Studio:

  1. Right-click the web project and click Manage NuGet packages
    image_thumb2_thumb2
  2. …and search for Microsoft ASP.NET Web Optimization Framework and click Install:
    image_thumb4_thumb2

Add CSS and JavaScript files to bundles

The first thing we want to do is define our bundles by specifying which CSS or JavaScript files should be bundled together. In standard ASP.NET MVC 4 projects the convention is to setup the bundles in a BundleConfig class inside an App_Start folder. However, for EPiServer sites you may want to use the EPiServer initialization engine instead.

Combine multiple JavaScript files into one

Since we want to setup our bundles when the website starts we’ll add an initializable module which will be invoked by EPiServer on startup:

[InitializableModule]   
public class BundlesInitializationModule : IInitializableModule   
{   
    public void Initialize(EPiServer.Framework.Initialization.InitializationEngine context)   
    {   
        // Setup bundles   
    }   
  
    public void Preload(string[] parameters) { }   
  
    public void Uninitialize(EPiServer.Framework.Initialization.InitializationEngine context) { }   
}

For this example I have two JavaScript files, one called video.js and one called main.js:

image_thumb_thumb3

To define a bundle including these two files I add some code to the Initialize method of the BundlesInitializationModule class I created earlier:

BundleTable.Bundles.Add(    
	new ScriptBundle("~/bundles/scripts")    
		.Include("~/Static/js/video.js")    
		.Include("~/Static/js/main.js"));  

Note that I specify a virtual path for the bundle. This can be whatever you like, but the convention is to prefix the virtual path with “bundles”.

Next I include the files I want to bundle. Note the order of the JavaScript files as I want the contents of the video.js file to be included first in the concatenated JavaScript file.

Now that we have defined our JavaScript bundle we can easily insert a link to it using the Render helper method and the virtual bundle path we specified earlier:

@Scripts.Render("~/bundles/scripts")

Note that you can link multiple bundles at once by comma-separating the aliases:

@Scripts.Render("~/bundles/jquery", "~/bundles/scripts")

The HTML output

The HTML output by the Render helper method depends on the debug setting of the web application. In other words, whether we have the debug attribute of the <compilation> element in web.config set to true or false:

<compilation debug="true">

When debug is enabled, the resulting HTML will link the original JavaScript files separately:

<script src="/Static/js/video.js"></script>
<script src="/Static/js/main.js"></script>

However, if we disable debug

<compilation debug="false">

…and reload the page we’ll see a link to the bundled and minified JavaScript file instead:

<script src="/bundles/scripts?v=A_gScVohD1KsFMa4Kp5Ku9rEJrzdJpYegYzDKQlaB4Y1"></script>

We’ll recognize the virtual path we specified for our bundle, but we can also see that a long hash has been added to the path. This is to ensure browsers can efficiently cache our bundled JavaScripts until the underlying JavaScript files are modified.

The JavaScript output

The original video.js file looked like this…

function playVideo() {
    // Just output an alert for now
    alert("I'll play a video!");
}

…and the original main.js file looked like this:

$(document).ready(function() {
    // Play a video
    playVideo();
});

If we browse to the bundled JavaScript (the path with the long hash) we can see that the two files have indeed been combined in the order I specified and then minified:

function playVideo(){alert("I'll play a video!")}$(document).ready(function(){playVideo()})

Combine multiple CSS files into one

Stylesheets are combined and minified in the same way as JavaScript files, we just need to use the StyleBundle class instead of the ScriptBundle class:

The bundled CSS file is also linked in the same way:

Include jQuery or other CDN-hosted JavaScript files

You can easily link a CDN-hosted JavaScript resource, including a local fallback if the CDN should become unavailable:

BundleTable.Bundles.Add(
    new ScriptBundle(
        "~/bundles/jquery", // Our alias
        "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.0.min.js") // CDN URL
    .Include("~/Static/js/jquery-1.9.0.js")); // Local fallback

Bundling and minifying LESS files

If you use a CSS framework such as LESS you need to add a bit of extra code to ensure the LESS code is parsed into CSS before bundling and minifying.

The following will create a bundle including two LESS files which will be parsed and minified:

BundleTable.Bundles.Add(
     new Bundle("~/bundles/styles", new LessTransform(), new CssMinify())
         .Include("~/Static/css/foundation.less")
         .Include("~/Static/css/main.less"));

Note: the LESS transform above requires you to add BundleTransformer to your project (available on NuGet):

image_thumb2