I stumbled upon the Google Page Speed Insights tools when testing ASP.MVC 3 site performance few days ago. After running the performance test, I found out that the web page I was testing has a performance index of 50% - i.e.things such as loading JS, CSS, and static files are taking away about half of the website loading time. Here are some steps I took to optimize the site and recover much needed speed.
Plan of Action
1- Enabling Gzip Compression
Gzip is a compression algorithm that is used by several web servers and browsers to send and receive compressed http responses. By default gzip is disabled on IIS (bummer ...). You could use IIS GUI to change the settings - but for those of you who are XML ninja's here are the few lines of code that will recover some speed for your .NET 4.0 /3.5 app running on IIS7.
Google Page Speed Insights tool recommended value for client caching static resources is one week but you can change cacheControlMaxAge="7.00:00:00" to any number of days/hours based on your product development cycle.
Result: Over 25% increase in rating on Google Page Speed Insights tool
2- Minifying your JavaScript and CSS Files
Caveat: .NET 4.5 supports minifying JS and CSS files out of the box with the new Bundle Class [1] unfortunately the features are not available in ASP.MVC 3.0.
There are several tools that can minify JavaScript and CSS files but the one I used for the my project is Yahoo UI Library compressor.
To add Yahoo UI Library compressor to your solution fire up Package Manager[2]in Visual Studio and type in the following four commands.
Step - 1 Add Yahoo UI Library DLL's to your project
PM> Install-Package YUICompressor.NET
PM> Install-Package YUICompressor.NET.MSBuild
PM> Install-Package YUICompressor.NET.NAnt
PM> Install-Package YUICompressor.NET.Web.Optimization
Step - 2 Create msbuild.xml file and point it to your JS and CSS files
Msbuild allows you to automate pre-build and post-build actions on a Visual Studio Project. To use msbuild:
2.1. Create a file called "Msbuild.xml" [3] at the root level of your project and copy the following xml file code into it. (you might want to modify the paths in the XML file to reflect your development environment)
2.2. Add the following code to the Post-Build event [4] of your web project.
After you add the post-build event you can then build your project and get minified versions of your JS and CSS files generated. (Tip of the hat to Black River)
3- Combile your Icons images into a single CSS Sprite
If you have multiple Icon files that are heavily used in your application, you can combine them into one file (CSS Sprite) and use a single file in your application for all your icons. There are several and efficient ways of doing sprites but if you have only few icons you can simply fire up your favorite image editor (I used Paint.Net) to create an image with transparent background and use it to consolidate your icons.
Plan of Action
1- Enabling Gzip Compression
Gzip is a compression algorithm that is used by several web servers and browsers to send and receive compressed http responses. By default gzip is disabled on IIS (bummer ...). You could use IIS GUI to change the settings - but for those of you who are XML ninja's here are the few lines of code that will recover some speed for your .NET 4.0 /3.5 app running on IIS7.
Code Snippet
- <system.webServer>
- <urlCompression doStaticCompression="true" doDynamicCompression="true" />
- <staticContent>
- <clientCache
- cacheControlMaxAge="7.00:00:00"
- cacheControlMode="UseMaxAge" />
- </staticContent>
- </system.webServer>
Google Page Speed Insights tool recommended value for client caching static resources is one week but you can change cacheControlMaxAge="7.00:00:00" to any number of days/hours based on your product development cycle.
Result: Over 25% increase in rating on Google Page Speed Insights tool
2- Minifying your JavaScript and CSS Files
Caveat: .NET 4.5 supports minifying JS and CSS files out of the box with the new Bundle Class [1] unfortunately the features are not available in ASP.MVC 3.0.
There are several tools that can minify JavaScript and CSS files but the one I used for the my project is Yahoo UI Library compressor.
To add Yahoo UI Library compressor to your solution fire up Package Manager[2]in Visual Studio and type in the following four commands.
Step - 1 Add Yahoo UI Library DLL's to your project
PM> Install-Package YUICompressor.NET
PM> Install-Package YUICompressor.NET.MSBuild
PM> Install-Package YUICompressor.NET.NAnt
PM> Install-Package YUICompressor.NET.Web.Optimization
Step - 2 Create msbuild.xml file and point it to your JS and CSS files
Msbuild allows you to automate pre-build and post-build actions on a Visual Studio Project. To use msbuild:
2.1. Create a file called "Msbuild.xml" [3] at the root level of your project and copy the following xml file code into it. (you might want to modify the paths in the XML file to reflect your development environment)
Code Snippet
- <?xml version="1.0" encoding="utf-8" ?>
- <Project xmlns="http://schemas.microsoft.com/developer/MsBuild/2003">
- <UsingTask TaskName="CssCompressorTask" AssemblyFile="bin\Yahoo.Yui.Compressor.Build.MsBuild.dll" />
- <UsingTask TaskName="JavaScriptCompressorTask" AssemblyFile="bin\Yahoo.Yui.Compressor.Build.MsBuild.dll" />
- <!-- You can set the $(Configuration) to "release" once you have YUI compressor working to on your development environment -->
- <Target Name="Minify" Condition="'$(Configuration)'=='Debug'">
- <ItemGroup>
- <!-- You can bundle multiple CSS files by adding them as <CssFiles ..> below -->
- <CssFiles Include="$(MSBuildProjectDirectory)\styles\Site.css"/>
- <!-- You can bundle multiple JS files by adding them as <JavaScriptFiles ..> below -->
- <JavaScriptFiles Include="$(MSBuildProjectDirectory)\scripts\jquery-1.4.1.js"/>
- </ItemGroup>
- <!-- OutputFile is where your minified files will be saved -->
- <CssCompressorTask
- SourceFiles="@(CssFiles)"
- DeleteSourceFiles="false"
- OutputFile="$(MSBuildProjectDirectory)\styles\style-min.css"
- CompressionType="Standard"
- LoggingType="Info"
- PreserveComments="false"
- LineBreakPosition="-1"
- />
- <!-- OutputFile is where your minified files will be saved -->
- <JavaScriptCompressorTask
- SourceFiles="@(JavaScriptFiles)"
- DeleteSourceFiles="false"
- OutputFile="$(MSBuildProjectDirectory)\scripts\jquery-min-1.4.1.js"
- CompressionType="Standard"
- ObfuscateJavaScript="True"
- PreserveAllSemicolons="False"
- DisableOptimizations="No"
- EncodingType="Default"
- LineBreakPosition="-1"
- LoggingType="Info"
- ThreadCulture="en-au"
- IsEvalIgnored="false"
- />
- </Target>
- </Project>
2.2. Add the following code to the Post-Build event [4] of your web project.
After you add the post-build event you can then build your project and get minified versions of your JS and CSS files generated. (Tip of the hat to Black River)
3- Combile your Icons images into a single CSS Sprite
If you have multiple Icon files that are heavily used in your application, you can combine them into one file (CSS Sprite) and use a single file in your application for all your icons. There are several and efficient ways of doing sprites but if you have only few icons you can simply fire up your favorite image editor (I used Paint.Net) to create an image with transparent background and use it to consolidate your icons.
To create the a css sprite file:
1- Create a transparent image background
2- Add your icons onto the transparent image (Space them evenly to easily find the icons for your CSS)
3- Once you have consolidated your icons into a single image file, save the file as [yourimage].png (I am using PNG to further compress the icon file - you can skip step 4 if you save your file in a format other then PNG)
4- If you save your icon collection file as .PNG you can use online services (such as tinypng.org / or other solutions) to further compress your file
5- Modify your CSS file and point it to the new image file
Note: When modifying your CSS files use background-position:right top; to pinpoint and attach your new icons to HTML elements.
E.g. Before consolidating icons
( three separate Requests go out to the server to fetch the image files i.e.- 781 X 3 = 2.1KB)
After consolidation
(One Request goes out to the server to fetch a single CSS Sprite - Only 1.5KB)
CSS before Consolidation
Code Snippet
- .check
- {
- background-image: url('images/check.png');
- }
CSS after consolidation
Code Snippet
- .check
- {
- background-image: url('images/sprite.png');
- background-position:0px 20px; /* the exact position of the image on the CSS sprite */
- }
In the above example with only 3 icon files there is over 29% file size reduction which will translate into performance increase for the application.
4- Miscellaneous Items
4.1. Running debug="True" in production environment is also one way of slowing down your application. You might want to double check on your compilation mode and make sure you don't have any development setting in web.config that made it through to your production box. (Obvious, right, but it is very easy to forget after four publish jobs and six Xcopies)
4.2. Having external CSS links between the header tags and external JS links at the bottom of an web page also improves performance.
4.3. Last but not least ... a healthy dose of daily prayer :)
[1] Bundling CSS and JS files is streamlined in ASP.MVC 4 (.NET 4.5) using the new Bundle Class.
[2]. In Visual Studio "View" > "Other Windows" > "Package Manager Console"
[3] I have used the name "msbuild.xml" for simplicity- you can use a different file name. If you choose a different file name you might also want to tweak the settings on step 2.2.
[4]. In Visual Studio Right click project from "Solution Explorer" > "Build Events Tab" > "Post Build Event Command Line"
Comments