Alexander Haneng
Jul 15, 2014
  8824
(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
What’s next after Google Optimize’s sunsetting?

Google has announced that it is sunsetting the Google Optimize and Optimize 360 services, forcing customers to explore new platforms and invest in...

Ynze | Jan 31, 2023 | Syndicated blog

What’s next after Google Optimize’s sunsetting?

Google has announced that it is sunsetting the Google Optimize and Optimize 360 services, forcing customers to explore new platforms and invest in...

Ynze | Jan 31, 2023 | Syndicated blog

Migrating from Providers to CMS 12 ASP.NET Identity with cookie tweaks

Notes on migrating a multi-site from Membership and Role Providers to ASP.NET Identity and changing cookie options dynamically.

Johan Kronberg | Jan 30, 2023 | Syndicated blog

Integrating generative AI in Optimizely CMS: A quick test with OpenAI

Some of the new AI services have received a lot of attention recently. Can you integrate them in Optimizely CMS? Of course, you can!

Tomas Hensrud Gulla | Jan 30, 2023 | Syndicated blog