Alexander Haneng
Jul 15, 2014
  9958
(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
Opti ID overview

Opti ID allows you to log in once and switch between Optimizely products using Okta, Entra ID, or a local account. You can also manage all your use...

K Khan | Jul 26, 2024

Getting Started with Optimizely SaaS using Next.js Starter App - Extend a component - Part 3

This is the final part of our Optimizely SaaS CMS proof-of-concept (POC) blog series. In this post, we'll dive into extending a component within th...

Raghavendra Murthy | Jul 23, 2024 | Syndicated blog

Optimizely Graph – Faceting with Geta Categories

Overview As Optimizely Graph (and Content Cloud SaaS) makes its global debut, it is known that there are going to be some bugs and quirks. One of t...

Eric Markson | Jul 22, 2024 | Syndicated blog

Integration Bynder (DAM) with Optimizely

Bynder is a comprehensive digital asset management (DAM) platform that enables businesses to efficiently manage, store, organize, and share their...

Sanjay Kumar | Jul 22, 2024

Frontend Hosting for SaaS CMS Solutions

Introduction Now that CMS SaaS Core has gone into general availability, it is a good time to start discussing where to host the head. SaaS Core is...

Minesh Shah (Netcel) | Jul 20, 2024

Optimizely London Dev Meetup 11th July 2024

On 11th July 2024 in London Niteco and Netcel along with Optimizely ran the London Developer meetup. There was an great agenda of talks that we put...

Scott Reed | Jul 19, 2024