Optimizing the use of the Google Font API

At Google, we're absolutely obsessed with making the web faster, and delivering the lowest possible latency to users. Naturally, with the Google Font API, we're concerned with how to minimize the performance impact of web fonts. This post presents a number of best practices for optimizing performance and also summarizes the results of extensive measurements with real-world integrations.

First, the recommendations:

1. Combine multiple fonts into one request.

One pattern we see frequently is a separate <link> tag for each of the font requests. Many users don't seem to know that you can easily combine multiple font requests into a single tag, just separating the fonts with a | character.

So, instead of:
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Droid+Sans">
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Lobster">

<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Droid +Sans|Lobster">

This simple trick will save one roundtrip to the server for each additional font requested, and also protect against blocking on older browsers which only have 2 connections open per domain at a time.

2. Don't put the @import in an external CSS

Unfortunately, Internet Explorer has bad performance when one external CSS file links to another using an @import directive. If it weren't for performance issues, it would be good to have the extra flexibility of putting the @import in the same CSS file that uses the fonts, but for best performance, put the <link> tag in the base HTML file.

When that's done, the Font API CSS will usually load in parallel with other external CSS files in the page.

3. Put the font request early

You should try to place the Font API link right after the opening tag. In general, the Font API link should never go after a <script> tag. As Steve Souders has pointed out in his blog post (http://www.stevesouders.com/blog/2009/10/13/font-face-and-performance/), if there's a script tag before the @font-face declaration, Internet Explorer won't render anything on the page until the font file is done downloading.

4. Don't ask for fonts you don't use

This may seem obvious, but if you don't actually use a font, don't request it in the API. You might miss this if you do your testing in Firefox or Chrome, which only load the font files needed to render the text on the page. Internet Explorer, by contrast, loads all the fonts requested, even if they’re not actually used.

5. Use tools to analyze your page's performance

An excellent resource is webpagetest.org, which runs your page in an instrumented IE browser, and displays waterfall graphs and other information. It’s also a great idea to use the “Inspect Element” resource graphs in Chrome. Also be sure to follow Steve Souders' blog, which contains tons of useful information about improving performance of web fonts.

Let’s take a closer look at a well-designed site, the home page of the Government of Chile (http://www.gobiernodechile.cl/). This is a (partial) resource timeline from Inspect Element in Chrome over a 3Mbps DSL connection: </script>

The second resource (“css”) is the invocation of the Google font API. As you can see, the request is placed very early in the waterfall, and a number of other requests are served in parallel. Around the time the first round of Javascript is done loading, the page is rendered for the first time (the blue line), and a second round of resources are loaded, also in parallel, including the two “font” resources. This waterfall clearly shows that the font requests aren’t blocking any other resources on the page. If the font request had been an @import in an external CSS, the waterfall would have been different.

Running the same page on webpagetest.org (Internet Explorer 8) shows similar results with respect to the font resources (only first 20 requests shown):

Unlike in Chrome, the Javascript requests of lines 6-9 do serialize (the fact that Chrome is much faster than IE is not just marketing!), but the font API request (line 12) and the font data (line 13) are, just as in Chrome, loaded in parallel. Rendering is, however, blocked until the font data is complete. To make font loading entirely asynchronous and avoid any possibility of blocking the rendering, use the Webfont Loader library. Note that parallel loading will not always be the case, but if you follow the recommendations above, there’s a very good chance of it, and it is always a good idea to use these tools to analyze and optimize the performance of your site.

We’re working with browser vendors (IE9 in particular) to fix the fact that rendering blocks on the font data.

A larger scale analysis of latency impact

To make sure that our recommendations are sound, and that we’re using the best strategy to serve web fonts, we did a detailed quantitative analysis of the impact of web fonts on page load time. We chose 28 popular sites that use the Google Font API, and measured the page load time both with web fonts and with the request to the Font API disabled. Each experiment ran 200 times, with three simulated network speeds: fast (roughly 100Mbps), medium (3Mbps), and slow (384kbps). All the tests were run on Internet Explorer 8, instrumented to report the page load time.

Each of the following graphs shows a distribution of the difference of the mean page load time with and without fonts. As you can see, on fast connections the distribution is consistent with a Gaussian curve centered around zero. In fact, the mean increase in page load time is 37ms (+/- 137ms), so a reasonable conclusion is that there is no measurable impact on page load time. Note that most webpages have a very high variance in page load times, so getting measurements more precise than a few hundred milliseconds is not feasible.

Fast (~100Mbps):

At medium network speeds, there seems to be a bias toward increasing page load times, with all samples save one coming in at between 0 and 500ms. Even so, the mean increase was only 34ms (+/-195ms), so the effect is barely significant.

Medium (3Mbps):

Finally, on slower connections, it is possible to see a definite impact on overall page load times, ranging from 250ms-1.5s for all but two of the samples. At these speeds, the mean increase is definitely significant, at 1016ms (+/- 302ms).

Slow (384kbps):

We wanted to find out exactly what was causing this impact on page load time on slower connections. A reasonable hypothesis is that it’s the bytes themselves. Thus, we made a scatterplot with the total (compressed) size of the fonts on the horizontal axis, and the delta page load time on the vertical. This plot shows a clear linear relationship:

Thus, users on high-bandwidth connections can enjoy web fonts with little or no impact on performance -- the web font request is served in parallel with the other elements on the page. Users on slower connections will see the impact of the additional bytes served. Fortunately, our team is working on ways of compressing font files even further, and users of the Google Font API will see the performance benefits as soon as this work is complete, with no additional effort.

By Raph Levien and Jeremie Lenfant-engelmann, Engineers on the Google Font API Team

No comments:

Post a Comment