Before launching a new website, there’s a checklist I go through, to make sure that everything is ready. One of the items in my checklist is to test the website against WebPagetest.
WebPagetest is a tool that was originally developed by AOL for use internally and was open-sourced in 2008 under a BSD license. The online version at www.webpagetest.org is run for the benefit of the performance community with several companies and individuals providing the testing infrastructure around the globe.
This tool tests any website against 6 major performance affecting factors, and provides a myriad of graphs and logs that make abundantly clear what might be slowing down your site.
In this post I’ll provide ways to make your site get straight A’s in WebPagetest.
Setup
To start this off, let’s setup our environment. We’ll just need the following:
- Visual Studio 2017
- Microsoft Azure account
In Visual Studio, let’s create a new empty ASP.NET Web Application project. Then, we’ll need the latest and greatest Umbraco NuGet package (I used version 7.12.4). Once it finishes installing, just launch the website and install Umbraco with all defaults. This will bootstrap Umbraco with the Starter Website, which we’ll use as our “guinea pig” for WebPagetest.
Next: publish it! We can use the publish wizard to automatically create our new WebApp and SQL Database in Azure. Before installing Umbraco in Azure, we’ll need to change the Web.config so that the install wizard is run again (I use Filezilla to change it in Azure):
Clear the Umbraco version number:
<add key="umbracoConfigurationStatus" value="">
Clear the Umbraco connection string:
<add name="umbracoDbDSN" connectionstring="" providername="System.Data.SqlClient">
With these changes in place, we’re good to go. This time, we’ll not use the defaults in the Umbraco install wizard, since we’ll want to use the SQL Database we’ve just created in Azure.
First test
For our tests, we’ll use the people page of the Starter Website. This is the score I got with a standard (S0) database and a basic WebApp:
Since this is a very small site, only used for demonstration purposes, half of the metrics are already cleared! However, this is not usually the case for bigger websites. For this reason, I’ll still present some solutions to improve the grade for these metrics.
First Byte Time
These test measures the time it takes for the first byte to reach the client’s browser after the initial http request.
There are two main factors that influence this result:
- Server power
- The webpage complexity (integrations with external services, complex logic involved, etc)
How to get an A
The easiest way to mitigate this problem is by caching. You can see how to do output caching in Umbraco by reading this old post of mine: https://blogit.create.pt////andresantos/2016/06/30/umbraco-and-donut-output-cache/.
Keep-alive Enabled
Keep alive is a method to allow the same tcp connection for HTTP conversation instead of opening a new one with each new request.
How to get an A
This setting is active by default in IIS, so, it’s also active by default in Azure WebApps, so it’s easy to get an A!
Compress Transfer
Gzip compresses your webpages, style sheets and javascripts, before sending them over to the browser. This drastically reduces transfer time since the files are much smaller.
How to get an A
Just add this setting to your Web.config file:
<httpcompression dynamiccompressionenablecpuusage="0" dynamiccompressiondisablecpuusage="90" nocompressionforhttp10="false" nocompressionforproxies="false"> <statictypes> <add mimetype="text/*" enabled="true"> <add mimetype="message/*" enabled="true"> <add mimetype="application/javascript" enabled="true"> <add mimetype="application/font-woff" enabled="true"> <add mimetype="application/font-woff2" enabled="true"> <add mimetype="application/vnd.ms-fontobject" enabled="true"> <add mimetype="application/octet-stream" enabled="true"> <add mimetype="*/*" enabled="false"> </add></add></add></add></add></add></add></add></statictypes> <dynamictypes> <add mimetype="text/*" enabled="true"> <add mimetype="message/*" enabled="true"> <add mimetype="application/javascript" enabled="true"> <add mimetype="*/*" enabled="false"> </add></add></add></add></dynamictypes> </httpcompression>
Compress Images
Image compression is minimizing the size in bytes of a graphics file without degrading the quality of the image to an unacceptable level.
How to get an A
In Umbraco, to get an A in this grade, you need to do two things:
- Crop every image and use srcsets where you can
- Use the PostProcessor plugin for Image Processor
Cropping an image is easy in Umbraco:
<div class="employee-grid__item__image" style="background-image: url('@person.Photo.GetCropUrl(width: 323, height: 300, quality: 85)')"></div>
In order to use the PostProcessor plugin, you just need to install it via nuget: https://www.nuget.org/packages/ImageProcessor.Web.PostProcessor/1.3.1.25.
Cache Static Content
Static content is content that changes rarely. For this reason it can be cached in the user’s browser to avoid downloading the same file over and over again.
How to get an A
Just set the time it takes for the content to expire in the user’s browser and add extra mime types if you want:
<staticcontent> <clientcache cachecontrolmode="UseMaxAge" cachecontrolmaxage="7.24:00:00"> <remove fileextension=".air"> <mimemap fileextension=".air" mimetype="application/vnd.adobe.air-application-installer-package+zip"> <remove fileextension=".svg"> <mimemap fileextension=".svg" mimetype="image/svg+xml"> <remove fileextension=".woff"> <mimemap fileextension=".woff" mimetype="application/x-font-woff"> <remove fileextension=".woff2"> <mimemap fileextension=".woff2" mimetype="application/x-font-woff2"> <remove fileextension=".less"> <mimemap fileextension=".less" mimetype="text/css"> <remove fileextension=".mp4"> <mimemap fileextension=".mp4" mimetype="video/mp4"> <remove fileextension=".json"> <mimemap fileextension=".json" mimetype="application/json"> </mimemap></remove></mimemap></remove></mimemap></remove></mimemap></remove></mimemap></remove></mimemap></remove></mimemap></remove></clientcache></staticcontent>
Effective use of CDN
A content delivery network (CDN) refers to a geographically distributed group of servers which work together to provide fast delivery of Internet content. A CDN allows for the quick transfer of assets needed for loading Internet content including HTML pages, javascript files, stylesheets, images, and videos.
How to get an A
In Umbraco, you can achieve this last grade by doing two things:
- Use an Azure Blob Storage for media storage by installing this nuget package: https://github.com/JimBobSquarePants/UmbracoFileSystemProviders.Azure.
- Create an Azure CDN for serving these blobs through a content delivery network.
After creating an Azure CDN service and waiting about an hour for it to be available, the following presents my configuration for the media assets to be provided by it:
<!--?xml version="1.0" encoding="utf-8"?--> <security> <services> <service name="LocalFileImageService" type="ImageProcessor.Web.Services.LocalFileImageService, ImageProcessor.Web"> <!--Disable the LocalFileImageService and enable this one when using virtual paths. --> <service prefix="media/" name="CloudImageService" type="ImageProcessor.Web.Services.CloudImageService, ImageProcessor.Web"> <settings> <setting key="Container" value="media"> <setting key="MaxBytes" value="8194304"> <setting key="Timeout" value="30000"> <setting key="Host" value="https://<umbracositename>.blob.core.windows.net/media"> </setting></setting></setting></setting></settings> </service> </service></services> </security>
<!--?xml version="1.0" encoding="utf-8"?--> <caching currentcache="AzureBlobCache"> <caches> <cache name="AzureBlobCache" type="ImageProcessor.Web.Plugins.AzureBlobCache.AzureBlobCache, ImageProcessor.Web.Plugins.AzureBlobCache" maxdays="365"> <settings> <setting key="CachedStorageAccount" value="DefaultEndpointsProtocol=https;AccountName=<accountname>;AccountKey=<accountkey>;EndpointSuffix=core.windows.net"> <setting key="CachedBlobContainer" value="cache"> <setting key="UseCachedContainerInUrl" value="false"> <setting key="SourceStorageAccount" value="DefaultEndpointsProtocol=https;AccountName=<accountname>;AccountKey=<accountkey>;EndpointSuffix=core.windows.net"> <setting key="SourceBlobContainer" value="media"> <setting key="StreamCachedImage" value="false"> <setting key="CachedCDNRoot" value="https://<cdnrootname>.azureedge.net"> <setting key="CachedCDNTimeout" value="1000"> </setting></setting></setting></setting></setting></setting></setting></setting></settings> </cache> </caches> </caching>
Conclusion
So, if you followed these tips correctly, you’ll be able to run WebPagetest and get the same result as I did:
You can find the complete report here: https://www.webpagetest.org/result/181127_2A_bea6941dcd20d38ab54c29409fca9363/.