Designing for Web Performance
Bibliographic Information
Designing for Performance
Replacing Image Requests
-
Combine images into sprites
-
Replace image files with CSS3, data URIs, or SVG versions
Sprites
Designing for Performance
We have a favorite!
We have a winner!!
-
We are applying a transparent background-color to these elements, and we’re telling it to not repeat the background-image across the entire width and height of the elements.
-
We use text-indent to move the text within the h1 off the visible area of the page and to allow the background-image to show through. There are a number of ways to move text off the visible section of the page but still make it available to screen readers; you can also try the following method for hiding visible text:This text-indent: 100% method may also significantly increase performance on the iPad 1 in cases where you are applying many animations to this element.
-
To get the star to show up to the left of the paragraph text, I’m applying the image to the :before pseudoelement for the paragraph. The :before selector creates a new, inline element so you can insert content before the content of the selected element. :after is also a psuedoelement you can use. These pseudoelements are supported in modern browsers, with partial support in Internet Explorer 8 and no support in earlier versions of Internet Explorer.
-
50% 25%
-
50px 200px
-
left top
CSS3
-
Can handle transparency
-
Can be overlaid on a background color
-
Eliminate an image request
-
Are super easy to change
Data URIs and Base64-Encoding Images
-
background-clip
-
background-color
-
background-image
-
background-origin
-
background-position
-
background-repeat
-
background-size
-
background-attachment
Remove Specificity
Minification and gzip
-
Apache: Use mod_deflate (http://bit.ly/1ttY0BG).
-
NGINX: Use ngx_http_gzip_module (http://bit.ly/1x6VsYF).
-
IIS: Configure HTTP compression (http://bit.ly/1ttXYts).
Caching Assets
Caching is critical for your site’s performance; assets that are cached do not need to be requested again from your server, saving a request. Caching works by sharing information with a user’s browser so it can determine whether to display the previously downloaded (cached) file from disk, or request the asset again from the server.
This information is communicated in an HTTP header, which is the core part of any request sent back and forth between a browser and your server. HTTP headers include lots of additional information like a browser’s user agent, cookie information, the type of encoding used, the language the content is in, and more. There are two kinds of caching parameters that can be included in a response header:
-
Those that set the time period during which a browser can use its cached asset without checking to see if there’s a new one available from your server (Expires and Cache-Control: max-age)
-
Those that tell the browser information about the asset’s version so it can compare its cached version to the one that lives on the server (Last-Modified and ETag)
You should set one of Expires or Cache-Control: max-age (not both), and one of Last-Modified or ETag (not both), for all cacheable assets. Expires is more widely supported than Cache-Control: max-age. Last-Modified is always a date, and Etag is any value that uniquely identifies the version of the asset, such as a file version number.
All static assets (CSS files, JavaScript files, images, PDFs, fonts, etc.) should be cached.
-
When using Expires, set the expiration up to one year in the future. Don’t set it to more than one year in the future, as that would violate the RFC guidelines.
-
Set Last-Modified to the date on which the asset was last changed.
If you happen to know when a file is going to change and you’d like to set a shorter expiration, you can do so, though a minimum of one month is still best practice. Alternatively, you could change the URL reference to the asset, which will break the cache and force the user’s browser to fetch a new version.
For a guide on enabling caching with an Apache server, read the Apache Caching Guide (http://httpd.apache.org/docs/2.2/caching.html). For a NGINX server, read NGINX Content Caching (http://nginx.com/resources/admin-guide/caching/).
Images
RESS, which stands for responsive web design with server-side components, is one option for creating and serving correctly sized images. You can improve performance by choosing which assets to serve to your user on the server-side, rather than optimizing them on the client-side. Your server can make smart decisions by looking at a user agent string, from which it can guess things like your user’s screen size, device capabilities like touch, and more. Tools like Adaptive Images (http://adaptive-images.com/) detect your user’s screen size and will automatically create, cache, and deliver correctly sized images based on your defined breakpoints (see Figure 5-3). In his book High-Performance Responsive Design (O’Reilly), Tom Barker outlines a number of RESS techniques and how to implement them.
Primarily, you need to ensure that only the appropriate content is being loaded at each breakpoint. Don’t join the other 72% of websites (http://bit.ly/1tBv6cT) that are serving up the same size responsive design site across screen sizes.
If you’re able to, implement automated tests that measure the total page weight for each of your chosen breakpoints. Tom Barker included an excellent chapter on continuous web performance testing in his book High-Performance Responsive Design, which outlines how to implement Phantom JS tests that measure each breakpoint’s performance, including YSlow score and total page weight.
You can also test this manually. Emulate a device using Chrome DevTools and use the Resources panel to see which image size is being downloaded for that device. Here is an example set of media queries in which I choose to serve a different image based on breakpoint:
@media (min-width: 601px) {
section {
background: url(big.png);
}
}
@media (max-width: 600px) {
section {
background: url(small.png);
}
}
Real User Monitoring
After choosing a real user monitoring tool, identify your site’s major pages to see how they perform for your users over time. The home page, top landing pages, any kind of checkout flow, and other high-traffic, important areas of your site should be included in your main reports. As you look at your users’ load time for these pages, segment the data in a few different ways to get a more holistic picture of your end-user experience:
-
Geographic location (near/far from a data center, areas where your main audience lives)
-
Network type (cellular, WiFi, etc.)
-
Median as well as 95th percentile total page load time
Why 95th Percentile?
The 95th percentile metric is another way to illustrate the performance pain points on your site. The median will give you a general understanding of how long a page might take to load for your user, but the 95th percentile metric is important to ensure that the vast majority of your users have an excellent user experience. The 95th percentile is the slowest 5% of your page views, but 5% is still a notable part of your user base. For RUM, 95th percentile tends to be a measure of how slow your users’ network connections are, and slower connections are always going to send the higher percentile through the roof. Note that Google Analytics provides averages for page load time, not percentiles.
Once you have this data, begin to analyze the differences between audience groups, like in Figure 6-11. How different is the median page load time from the 95th percentile? How does the site perform for people in other countries? How about your users on mobile devices? Are there major differences in load time between your top five pages?