As a web developer, it’s important for you it’s important for you to look for imaginative ways to improve your page load times. This often involves reducing the number or weight of the HTTP requests that a user makes when loading a web page. In this chapter we examine bundling and minification, which will help you make fewer HTTP requests and severely reduce the weight of your web pages. ASP.NET 4.5 has fantastic new features that allow you to apply both techniques to your web application easily and automatically. By the end of this chapter, you’ll be able to apply these techniques to your web applications in no time!
Most developer-written JavaScript or CSS contains loads of extra spaces and line breaks that don’t get run when the code is executed. Removing these unnecessary spaces and line breaks, a technique known as minification, reduces the overall size of the file and, in turn, results in faster page load time, without affecting the integrity of its contents. The code downloads and executes faster, but the code will run in the very same manner—it’s an easy win!
When CSS or JavaScript is minified, it starts to lose its readability. It’s important to understand that while humans might struggle to read the code, the browser will have no trouble processing it. This is a necessary evil because the removal of whitespace and the obfuscation that results will ultimately help the file load faster. The built-in support for minification that comes with Visual Studio 2012 is also intelligent enough that while you’re developing you’ll be able to see the full, unminified code. When you run your website in Release mode, the code will automatically get minified on the fly for you.
In the Surf Store application, we’ve added HTTP caching and compression, which has drastically improved the page load speed. But if we run the sample application as it stands against the Google PageSpeed tool, there are still things that need to be done in order to improve our PageSpeed score. One of the most important things you can do to boost page load time is minify JavaScript (figure 5.1).
If we take a typical CSS file and minify it, the results compared to the original version are very different in both appearance and file size. The next listing shows a CSS snippet before it’s been minified.
As you can see, the CSS contains unnecessary spaces, tabs, and line breaks. Although this makes the code a lot easier to read and prettier to the human eye, ultimately it adds extra weight to the overall size of the file. The next listing shows you what the code looks like after it’s been minified.
h1{#1 font-size:30px;line-height:36px}h1 small{font-size:18px}h2{font- size:24px;line-height:36px}h2 small{font-size:18px}h3{font-size:18px; line-height:27px}h3 small{font-size:14px}
Differences between the two listings are visible immediately. The code has no spaces, and the comments, tabs, and line breaks have been removed, making the code snippet a lot smaller. These two examples use a small piece of code, but imagine the difference this could make if minification were applied to all the CSS and JavaScript in your application.
JavaScript can be minified and obfuscated to reduce the file size even further. Look at the following JavaScript code before it has been minified.
The code in the next listing has been obfuscated and minified, and there’s a big difference in the readability of the file when you compare it to listing 5.3. Although the minified code isn’t easy on the human eye, it’s perfectly acceptable to use the compressed version on the server after development has been completed.
$(document).ready(function(){$("#barcodeValue").keyup(function(a){if(a.key Code==13){validateString($("#barcodeValue").val(),$("#barcodeType option:selected").val())}});$("#barcodeValue").hide();$("#CreateButton") .hide();$("#alertBox").hide();$("#progressBar").hide();$("#infoLink").hide(); $("#barcodeType").change(function(){$("#barcodeValue").show();$("#CreateButton") .show();shouldPrepend()})});
Developers often like to keep two versions of their code: one for debugging and one for deployment in a live environment. When you visit the jQuery website, you’ll notice that there’s an option to download a minified version of jQuery. The filename will often end in .min.js, which has become the standard method of naming the files. The unminified version will be named something like jquery-1.8.0.js, while the minified version will be called jquery-1.8.0.min.js. This makes it easy to identify the files while you’re developing your application.
Table 5.1 contains a list of common JavaScript and CSS frameworks and the differences in their file sizes before and after minification.
Filenames |
File size before minification |
File size after minification |
File size savings |
---|---|---|---|
jQuery | 225.78 KB | 93.28 KB | 58.68% |
jQuery Mobile | 240 KB | 91 KB | 62% |
Twitter Bootstrap CSS | 98 KB | 80 KB | 19% |
As you can see from table 5.1, the size savings vary considerably across the different files, and is probably due to factors such as whitespace, comments, and line breaks. If we can achieve this level of file size savings with no functional changes to our code, it seems obvious that minifying the code is a free and easy win.
Later in this chapter we’re going to automatically apply minification to the files in the Surf Store application with the new built-in features in ASP.NET 4.5 and Visual Studio 2012. If you prefer to minify your files manually, there are many online tools that allow you to do so.
The online YUI compressor uses the Yahoo! YUI compressor to easily minify both JavaScript and CSS. All you have to do is paste the contents of the file into the textbox and you’ll be presented with an option to download the minified file. The web application is available at http://refresh-sf.com/yui/.
Another tool for use with JavaScript is the Google Closure Compiler. It’s used in many of Google’s JavaScript apps, including Gmail, Google Web Search, Google Maps, and Google Docs. An online version of the tool is available at closure-compiler.appspot.com.
There are many other tools available on the web, but keep in mind that each might use a different algorithm and a slightly different method of minification. What’s important is that they all use minification techniques that significantly reduce the size of these files. The only downside to using these online tools is that the minification process is manual; you’ll have to upload each version of your CSS and JavaScript and wait for the download before adding it back into your project. Later in the chapter, we’re going to explore the built-in minification support that Visual Studio 2012 offers, which will automatically handle this for you.
A technique that works well with minification is bundling. You might find that your web pages contain references to many CSS and JavaScript files. While this makes our lives easier as we’re developing our websites, having more than one CSS or JavaScript file once the code goes into production isn’t always ideal. More file references mean more HTTP requests, and in our quest to improve the overall speed of a website, we need to reduce the number of requests that a web page makes. The easiest thing to do is to combine all of the JavaScript into one file, and combine all of the CSS into another file. This technique is known as bundling. If you had four JavaScript files before bundling, you would have had four HTTP requests. If the JavaScript files are bundled, you’ll only have one HTTP request, which will speed up your website considerably!
In a standard web page, each component is requested separately by the browser and returned by the server. Once the code reaches the browser, it doesn’t care if it’s neatly formatted and split into a logical order. The browser will execute the code regardless and by bundling the files we’re making it a lot quicker for the browser to receive the code that it needs to execute. Bundling is easy to implement and it seems a waste not to take advantage of this simple technique to speed up your web pages. Utilizing bundling and minifying together allows you to amplify those savings even more.
In this section you’re going to apply bundling and minification to our Surf Store application. Some great features included in the release of Visual Studio 2012 will boost and improve your page speed. You’re going to focus on the bundling and minification features that can be found under the System.Web.Optimization namespace.
This namespace allows you to bundle and minify all of the JavaScript and CSS in the project folder simply by sending a URL request to a preset virtual folder path. This code will work in both ASP.NET Web Forms and ASP.NET MVC, and is included automatically when you create a project in Visual Studio 2012. As you can see in figure 5.2, it can be found in the Solution Explorer under the App_Start folder.
It should be noted that if you choose an empty ASP.NET MVC project template, you won’t find this class in your project. It is the simplest type of ASP.NET project and it doesn’t contain the full set of classes that you might need.
This BundleConfig class contains code that allows you to create Script and Style bundles that will bundle and minify the files. You’re going to run through an example in both ASP.NET MVC and Web Forms, but first it’s important to understand how each request is handled by ASP.NET.
In order to create a Script bundle, you’ll need to instantiate it by referencing a virtual path to the files that you want to bundle. The following listing contains code that you’ll need to implement or replace in the RegisterBundles() method of the BundleConfig class.
The first virtual path referenced in the ScriptBundle is a reference to a file that doesn’t exist and can therefore be anything. In this case, I have pointed it to “~/Styles/Css”. The code will then service any requests to the path provided. For example, if we want to apply this to CSS, we request:
<link href="/Styles/Css" rel="stylesheet">
As the website compiles and runs for the first time, ASP.NET will search the directory shown in the previous listing, and it will bundle and minify all the CSS files it finds. When the virtual directory for the bundle is requested, it will send back a single HTTP response with all of the CSS combined and minified together. The same piece of code can be applied to all JavaScript files in a directory by simply changing the path to:
<script src="/Scripts/Js" type="text/javascript"></script>
By referencing the files, ASP.NET 4.5 will generate a reference to the bundled and minified CSS and JavaScript files in the respective directories. For example, instead of seeing two CSS file references in the HTML, we now see only one combined file to give us only one HTTP request. Figure 5.3 shows the data that is inside the newly combined file.
The code in figure 5.3 has been word wrapped and cut short to make it easier to read, but you can see there are no spaces and the code is pretty difficult to read. Visual Studio has taken care of the hard work for us, and it only took a matter of minutes to implement this change. If you mistakenly specify a path of a script file or CSS file that doesn’t exist, the framework will gracefully handle it for you and not throw any errors. You won’t get any runtime exceptions and the framework will continue to bundle and minify the rest of the files.
The great thing about this new feature is that you don’t need to run any tools or manually minify or bundle these files—it happens automatically when you run your application. You’re also in total control as you can switch it on and off as you need it. This quick change easily handles bundling and minification for you and it’s definitely a step in the right direction.
This optimization will only occur under Release mode. You may notice that the files you’ve requested are not being bundled while you’re developing. By default, bundling is automatically disabled under Debug mode to make life easier for the developer to read and update the code. Once you compile your application under Release mode, the optimizations take place and bundling is enabled. If you need to test this feature while in Debug mode, you can temporarily override it by setting BundleTable.Enable-Optimizations = true in your BundleConfig.cs file. This will minify and bundle your files while in Debug mode.
In chapter 4 we covered Expires Headers and how they notify the browser to cache static resources for a specified duration. Before a web page requests a resource, the browser first checks its cache to see if it has a resource with a matching URL. This can sometimes be problematic because as you’re developing and releasing new changes to your application, your users might have older versions of these files in their browser’s cache. One option was to force refresh of the cache using file versioning, or file revving, and this appends a query string onto the end of the filename.
<link type="text/css" rel="stylesheet" href="/Styles/bootstrap.css?v=1.1">
ASP.NET 4.5 automatically adds a hashcode to the query parameter for you.
<link type="text/css" rel="stylesheet" href="/Styles/ bootstrap.css?v=ABnfFdbAnRuas7H">
If you updated the contents of one of the files and they are bundled using the new optimization feature, a new hashcode will be appended to the end of the filename automatically. This requires no extra code and is simply handled for you.
As long as the contents of the bundle don’t change, the ASP.NET application will request the bundle using this hashcode. If any file in the bundle changes, the ASP.NET optimization framework will generate a new hashcode, guaranteeing that browser requests for the bundle will get the latest bundle and force a refresh of the cache. Bundles also set the HTTP Expires header to expire one year from when the bundle is created. This means you’ll automatically get the benefits of HTTP caching when creating your bundles.
You’ve learned a bit about the process of bundling in Visual Studio 2012, and now it’s time to dive into specific coding examples. This section covers the steps that you’ll need to perform in order to enable bundling in your ASP.NET MVC web application. You’ll be using the Surf Store application as a reference for this example.
When you create an MVC 4 project in Visual Studio 2012, you’ll be presented with a screen similar to the image in figure 5.4 which shows the available project templates.
Once you’ve chosen your project template, a BundleConfig.cs file will appear in your App_Start folder of your project. As already mentioned, this can be used to set the Script and Style bundles and their associated paths.
The following listing shows how a default Global.asax file will look when it contains a reference to the BundleConfig class.
The Global.asax file will register the bundles that you’re about to set up. The next listing contains the code needed to set up your bundles in the BundleConfig class.
The previous listing shows how the different bundles in an application can be set up. You’re able to add multiple bundles to the BundleConfig class, then call them by their virtual path. Finally, you need to add these bundles and their virtual paths to the Layout view. Navigate to the _Layout.cshtml master view file in your Solution Explorer, as shown in figure 5.5.
You’re using the JavaScript and CSS file references from listing 5.7. Open the view and reference the JavaScript and CSS files using the default bundles. Two new HTML helpers have been introduced in the ASP.NET 4.5 framework: @Styles and @Scripts. Both, as shown in the next listing, can be used as an easy way to render the full HTML you need to reference your scripts and styles.
When the application is compiled and run, the HTML helpers in the previous listing will produce HTML similar to that in figure 5.6.
The code in figure 5.6 will bundle and minify all the CSS and JavaScript files in their respective directories. Notice the hashtag appended to the end of the filename. This hashtag is dynamic and will change only when the contents of the file change. By appending a different hashtag to the filename each time the contents change, you’re effectively ensuring that your users will receive a fresh copy of the contents each time they visit your website.
If you run the page against the developer tools in Internet Explorer, you can immediately see the differences. As shown in figure 5.7, the page requested four static files previously, which meant four HTTP requests.
After applying the changes to the Layout view, the HTTP requests have been reduced and you can see the virtual paths that you referenced in the BundleConfig class in figure 5.8.
Applying bundling to your ASP.NET MVC application has been made really easy with the new features in Visual Studio 2012. The new HTML helpers work with both the Razor and ASPX view engines. They are easy to use and don’t require major changes to your existing development workflow.
In the .NET 4.5 framework, ASP.NET MVC and ASP.NET Web Forms benefit from the System.Web.Optimization namespace. Applying bundling and minification in ASP.NET Web Forms is an easy process that is handled when you create a Web Forms project in Visual Studio 2012. You’ll notice in figure 5.9 that a BundleConfig.cs file has been created under the App_Start folder.
The Global.asax class file in your Solution Explorer will contain the following lines under the Application_Start method. The listing shows how a default Global.asax file will look when it contains a reference to BundleConfig.cs class file.
The Global.asax file in the listing will register the bundles you’re about to set up. It will do so as the application starts for the first time, so they’re ready to use as and when you need them. The following listing shows how to set up the correct bundles in the BundleConfig class.
The listing contains the code that will initialize the bundles for the JavaScript and CSS files. By using the BundleConfig class, you’re able to specify which files will get minified and bundled when the application starts. Next, navigate to the Site.Master file in the Solution Explorer (figure 5.10).
Open the master page and reference the JavaScript and CSS files using the default bundles. Two new HTML helpers have been introduced in the ASP.NET 4.5 framework: Styles and Scripts. They can both be used to render the full HTML that you need to reference your scripts and styles. This listing contains the code you need to apply to the Surf Store application.
The Scripts and Styles HTML helpers will minify and bundle the code when you’re in Release mode. When you’re in Debug mode, the helpers will simply return all of the JavaScript and CSS in individual HTML tags. When the application is compiled and run in Release mode, the code in listing 5.11 will produce HTML similar to that in figure 5.11.
The code in listing 5.10 will bundle and minify all the CSS and JavaScript files in the respective directories. Notice the hashtag that has been appended to the end of the filename. This hashtag will be dynamic and only change when the contents of the file change. By appending a different hashtag to the filename each time the contents change, you’re effectively ensuring that your users will receive a fresh copy of the contents.
If you run the application and check the Network Traffic tab in Internet Explorer’s developer tools (figure 5.12), you can immediately see the differences. The page previously requested four static files, which meant four HTTP requests.
After applying the changes to the Site.Master page, the HTTP requests have been reduced and you can see the virtual paths that you referenced in the BundleConfig class (figure 5.13).
Adding these changes to the sample Surf Store application has been quick and easy. Although you’ve run through standard implementations using bundling support in ASP.NET 4.5, I really like that this feature supports a rich extensibility API that enables you to customize the bundling settings to your personal needs.
It’s worth mentioning the steps you’ve taken this far to improve the page speed of the Surf Store application. As of now, you’ve added:
All of these features can and should be applied together to achieve the maximum effect on the improvement of your overall page load time. Is it worth adding compression if you’re minifying the file or vice versa? Definitely, because the files can still be compressed further after you’ve minified them.
By adding HTTP caching on top of this, you’re also reducing the number of HTTP requests that the user’s browser needs to make when visiting your website. All of these techniques are stacking up on one another to produce a faster, leaner, and more efficient website with extremely fast load times (figure 5.14).
Minifying the CSS and JavaScript in the Surf Store application has been an easy task using the new features built into ASP.NET 4.5. You were able to minify and bundle multiple files together, which had a big impact on your overall page speed. The Surf Store application’s Google PageSpeed score was 89 at the end of chapter 4. If we test the Surf Store application after minification and bundling (figure 5.15) you can see even more improvement. The PageSpeed score has jumped to 93.
Our minification and bundling efforts show good results when you run the website against the Yahoo! YSlow tool (figure 5.16), as well. Our performance went from a score of 90 to 91 and bumped us up to a grade A!
The changes have significantly improved our page weight and the number of HTTP requests. Figure 5.17 shows a before and after result.
You’re slowly reducing the number of HTTP requests that the sample Surf Store application needs to make. These changes have not affected the overall integrity of the code, but have boosted and improved the performance and load times of the application.
In figure 5.17, the chart on the left shows a total of 13 HTTP requests and a total page weight of 1049.8K. The chart on the right, after you’ve applied minification and bundling, tells a different story. You’ve reduced the number of HTTP requests to 11 and reduced the total page weight to 835.3K. This is pretty impressive and improvements were all made with the built-in support that ASP.NET 4.5 offers. Imagine what these changes could do for your web application!
In this chapter you’ve learned the all-important aspects of minifying and bundling your CSS and JavaScript files. In doing so, you’ve drastically reduced the size of the requested files. You’ve also reduced the number of requests each web page needs to make, giving you a two-way win.
There are new optimization features in ASP.NET 4.5 that are available with out-of-the-box support in Visual Studio 2012. They make it easy for you as an ASP.NET developer to apply minification and bundling to your web application.
It may seem like such a subtle difference when using the techniques that we covered in this chapter, but minification and bundling can seriously improve your page load times and save on the number of bytes your users need to download. It takes no time at all to apply it, and your users will definitely benefit from this change. Over the past few chapters, you’ve been building a basic foundation of simple techniques that are beginning to add up to a substantial toolkit. Together, these optimization techniques form the basis of a highly optimized website. In the next chapter, we begin to dive into HTML optimization techniques and look at how you can harness the power of HTML5 to improve the performance of your web applications.
18.219.123.84