Calling all developers! We invite you to provide your input on Feature Experimentation by completing this brief survey.

 

Alexander Haneng
Jul 15, 2014
  10209
(3 votes)

EPiServer CMS Site Performance Part 2: Bundling and Minifying

Next we will look at reducing the number of requests, reduce bytes on the wire, and leveraging browser caching for our EPiServer CMS site to increase performance.

Bundling and minifying JavaScript and CSS files
A good place to start to reduce the number of requests and bytes is looking at the JavaScript and CSS files we have included on every page. On our site we have 3 CSS files and 4 JavaScript files, and Google PageSpeed complains about them not being minified and having too short browser cache expiration dates set (24 hours). We can combine the CSS files into one CSS file and the JS files into one JS file, minify the combined files and set the browser cache expiration date to at least 1 year into the future.

<!--CSS--> <link rel="stylesheet" href="/css/bootstrap.css" > <link rel="stylesheet" href="/css/style.css"> <link rel="stylesheet" href="/css/CloudClinic.css"> <!--JS--> <script src="/js/jquery.js"></script> <script src="/js/jquery.mobilemenu.js"></script> <script src="/js/jquery.ui.totop.js"></script> <script src="/js/jquery.equalheights.js"></script>

There are many ways to bundle and minify files using third party tools, but as of ASP.NET 4.5 it is included in the framework, so we might as well use that. Currently a default EPiServer CMS project is set to .NET version 4.0, so the first step is to set it to .NET 4.5. Right click the project in VS and select properties. Change “Target framework” to “.NET Framework 4.5” and build your project.

image

To get access to the System.Web.Optimization framework we need to install a package from nuget. Open the “Packet Manager Console” and run the following line:

Install-Package Microsoft.AspNet.Web.Optimization

Now we are all set to bundle our files.

Creating the bundles
If you don’t already have an “App_Start” folder in the root of your project, create it. Create a new class in this folder named “BundleConfig.cs”. In our case we have created one bundle for our JavaScript files and one bundle for our CSS files, but you can create multiple bundles.

using System.Web.Optimization; namespace CloudClinic { public class BundleConfig { public static void RegisterBundles(BundleCollection bundles) { bundles.Add(new ScriptBundle("~/Bundles/JS").Include( "~/js/jquery.js", "~/js/jquery.mobilemenu.js", "~/js/jquery.ui.totop.js", "~/js/jquery.equalheights.js") ); bundles.Add(new StyleBundle("~/Bundles/CSS").Include( "~/css/bootstrap.css", "~/css/style.css", "~/css/CloudClinic.css") ); } } }

Registering our bundles
We need to register our bundles in the Global.asax.js file like this:

using System.Web.Mvc; using System.Web.Optimization; namespace CloudClinic { public class Global : EPiServer.Global { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); //Register JS and CSS bundles BundleConfig.RegisterBundles(BundleTable.Bundles); } } }

Using our bundles
Now we can swap our old CSS and JS files with the new bundles in our .cshtml file.

<!--CSS--> @Styles.Render("~/Bundles/CSS") <!--JS--> @Scripts.Render("~/Bundles/JS")


The end result
By loading the page again and viewing the source we can see the end result. (Note: If you have debug=”true” in your web.config the files won’t be bundled, so make sure to set it to false first.) The files have been bundled into just two files, they have been minified, the browser cache expiration has automatically been set to 1 year into the future and by adding a version hash query string we ensure that if we make any changes to the files the browser gets the latest version.

<!--CSS--> <link href="/Bundles/CSS?v=GSQWO59HgwIEQn34xDiBFOx9GFxcmzxP29G-QcjFvn41" rel="stylesheet"/> <!--JS--> <script src="/Bundles/JS?v=pUrWyl423vnnVLCmPyX5AF4ZNMCq1q65jNhtv0FcBL41"></script>

image

Bytes transferred: 326.5KB (was 333.3KB)
Requests: 30 (was 35)
Time: 1.16 seconds (was 1.27 seconds)

 

Go to Part 3: Optimizing images and using sprites

Jul 15, 2014

Comments

Petter Klang
Petter Klang Jul 15, 2014 12:43 PM

What happened to the minifying part? =)

Jul 15, 2014 12:53 PM

Bundling, minifying and far future cache expiration is all done in one operation. :-)

Petter Klang
Petter Klang Jul 15, 2014 01:47 PM

So minfiying only gave you 0.6k on your js?

You only writing a and b as variable names from the start then? =)

Petter Klang
Petter Klang Jul 15, 2014 02:08 PM

Don't you need the BundleTable.EnableOptimizations = true;?

http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

Jul 15, 2014 02:15 PM

Of course I only user a and b as variable names. Descriptive variable names are for wusses. :-)

The reason is that jquery.js already was minified and the other 3 JS files are pretty small (5KB in total).

The minification of the CSS files however saved me 6KB.

Jul 15, 2014 02:17 PM

You only need to set BundleTable.EnableOptimizations = true if you want to run the site with files bundled and debug = true.

Petter Klang
Petter Klang Jul 15, 2014 02:28 PM

I see, thanks for the clarification.

valdis
valdis Sep 12, 2014 10:58 AM

What about bundling conditionally? :) I cases when you need to reproduce client-side issue directly in production env..

valdis
valdis Sep 12, 2014 10:58 AM

What about bundling conditionally? :) I cases when you need to reproduce client-side issue directly in production env..

Sep 12, 2014 02:46 PM

Valdis: If you need to debug javascript in production you can:
a) Set debug = true in web.config
or
b) Set BundleTable.EnableOptimizations = false in code.

Please login to comment.
Latest blogs
Level Up with Optimizely's Newly Relaunched Certifications!

We're thrilled to announce the relaunch of our Optimizely Certifications—designed to help partners, customers, and developers redefine what it mean...

Satata Satez | Jan 14, 2025

Introducing AI Assistance for DBLocalizationProvider

The LocalizationProvider for Optimizely has long been a powerful tool for enhancing the localization capabilities of Optimizely CMS. Designed to ma...

Luc Gosso (MVP) | Jan 14, 2025 | Syndicated blog

Order tabs with drag and drop - Blazor

I have started to play around a little with Blazor and the best way to learn is to reimplement some old stuff for CMS12. So I took a look at my old...

Per Nergård | Jan 14, 2025

Product Recommendations - Common Pitfalls

With the added freedom and flexibility that the release of the self-service widgets feature for Product Recommendations provides you as...

Dylan Walker | Jan 14, 2025