Performance and font optimization strategy

I’m developing in my head a strategy for improved performance, particularly font handling.

Google Chrome has this super nifty feature where you can emulate another device (particularly mobile devices) including connections, so you can see how the site behaves. At the moment our load time on an unprimed cache is really bad for poor mobile connections, I’m talking 10s or more. I saw that for real when I used an android phone and going to suttacentral.net was a traumatically bad experience. I believe the standard to strive for is 2s maximum load time, as users tend to say ‘stuff this’ if a site takes more than 2s to load.

I am quite confident we could cut load time by 80% - or to put it another way, after 2s, be able to display the content of the site, even if not absolutely everything is loaded.

In terms of size (all sizes are gzipped) for components of the home page, it goes like this:

  1. HTML: 20KB - it would be smaller, but for cache optimization purposes I include all the epigraphs in the home page HTML, javascript stealthily chooses an epigraph to display. Having one and only one version of the home page (instead of a different version, one for each epigraph) really helps with cloudflare edge caching.
  2. CSS: 14kb. Although 80% of css is not needed for displaying the home page (which includes header and footer), 14kb is small by any standard. However it might be worthwhile inlining some of the CSS as an inline stylesheet, for example the quicker the browser sees a font-face declaration, the quicker it can start downloading the font. Important on high latency connections.
  3. JS: 47kb. Although not huge, our javascript assets can delay page loading by up to a second on slower mobile connections. Although javascript is ideally loaded last, in actuality, Chrome starts downloading the javascript before it starts downloading webfonts, this delays the fonts being available for however long it takes to finish downloading the javascript.
  4. Fonts ~400kb: The fonts in total to render the home page come to about 400kb, mostly Skolar (there are also some font variants not used on the homepage). The two most important fonts are the header fonts; Skolar sc and Hetu sc.

The load time reduction strategy would go like this:

  1. Divide the JS into essential and deferable. Essential is probably like 2kb.
  2. Divide the fonts into essential and deferable. Essential fonts are inlined into the CSS using Base64, this saves one or more requests and means the fonts are available the instant the CSS is parsed. I consider the essential fonts to be skolar sc and hetu sc, both for displaying the logo correctly, and because a FOUT from normal -> small caps is quite jarring! Skolar sc is quite large, so the inline component should be subsetted to ‘:wheel_of_dharma:SutaCenrl’ reducing it to ~5kb.
    Deferable fonts would be loaded in the background but not delay page rendering, a fallback font would be used until the webfont is downloaded. A 500ms (or perhaps 1000ms) FOUT guard could be used for the benefit of fast connections.
  3. The final high-powered option is to inline stuff into the HMTL. Both the JS and CSS are candidates for this (inlining as in inserting a <style>...</style> or <script>...</script> element into the HTML, not the other sense as attributes on elements).

What happens at the moment at Jhanagrove with it’s 700ms round trip to Geosynchronous orbit with an unprimed browser cache is this:
0ms: Browser pointed at suttacentral.net.
700ms: DNS server responds with IP address, browser requests page.
1400 ms: HTML arrives, parses it and sends request for CSS and JS assets.
2100ms: CSS arrives, parses it and sends request for webfonts.
2800ms: Webfonts arrive. Page can finally be displayed.

What happens if the CSS and Fonts are inlined into the HTML, is this:
0ms: Browser pointed at suttacentral.net
700ms: DNS server responds, browser requests page.
1400ms: Everything arrives. Parses it and renders the page.

Inlining can thus easily cut load time by 50% on high latency connections. All of the big sites do inlining for this reason. Inlining is very powerful but like most very powerful things it should be used sparingly.

With quite minimal changes we could get the assets download required, down from 500kb, to about 100kb - the 80% load time reduction. I believe that is the low hanging fruit, if you went for higher hanging fruit a 90% reduction would be possible.

I believe targeting the ‘unprimed cache’ situation is important because generally about 50% of page views are from new visitors. Maybe 50% of those users are in the fast internet belt around USA/Europe, but that still leaves 25% of page views being on poor connections.

Implementing a more explicit ‘fall back font’ strategy will also go well with pure WOFFification. For example inlining quickly blows out if you have to inline more than one font type, but if we are using only WOFF, it is easy to just inline the WOFF font, end of problem.

2 Likes

Okay, sounds fine, so far as I understand it.

Just remember, in our “next-gen” fonts, we plan to not have separate small-caps anymore, instead use font-feature-settings, which, unlike font-variant, chooses the actual small-caps. This applies to both serif and sans. Unless you think otherwise?

Not-really-related: I’ve started adding some Tibetan texts: http://suttacentral.net/bo/dq95

Can you enable Tibetan Machine Uni for the Tibetan texts? The font is installed by default on Ubuntu, but you can download the latest version here. Given that there are not many widely available Tibetan fonts, and many people using this will have it installed already, I wonder if it’s possible to check whether it’s installed before applying it?

I’m proposing using a very small subset of smallcap fonts. This would actually go under a different font name, something like ‘skolar sutta web sc title’ so as to avoid conflicts and be used only for rendering the title, this allows the browser to download much less before it can correctly render the header (and also on the home page, the ‘Sutta Central’ title which uses the same font)
As for how the bulk of the smallcap fonts are handled, that is a separate matter, using a font-feature setting sounds fine, my understanding is that font feature is not very well supported at the moment? If that is the case, then using a special subset for the really important stuff sounds like a good measure as it means the header will still render correctly on most browsers even if they don’t support the smcp feature.

If at all possible we should use a font which can be downloaded from Google or Cloudflare or another CDN. I’m guessing this isn’t an option with Tibetan.

Isn’t it the case that the browser only downloads a font-face font if its required on the page and only if its not already present on the OS? In other words, doesn’t what you want happen automagically? Am I missing something here?

Oh, okay.

Over 75% with webkit prefix.

If we lose a few on the sutta headings and the like, oh well, they’ll just see the regular font. But you’re right, a subset for the header sounds good. What about inserting the relevant glyphs as inline CSS binary via Base64?

As far as I know, no.

No, it’s probably just me. Carry on.

Yep, base64 encoding of the binary data is the technique I am referring to.

Actually, let’s try using this font instead:

https://sites.google.com/site/chrisfynn2/home/fonts/ddc-uchen

It seems to harmonize better with Skolar, with a lower contrast and generous size.

As you said above. I read too quickly!

Okay I added it. font-family is “DDC Uchen”

It’s now working on site, eg

Probably a good idea to remove the roman glyphs and numerals. These are actually quite nicely formed and cover a good range of Unicode, so the font is useful purely as a Roman font for Sanskrit. However for us it just adds weight and means we display the Roman parts in a font that is quite different to our usual.

Also, these texts have line numbers, like the CBETA ones. It would be nice to have a “display by line number” feature as we do for the Chinese texts.

In fact the Tibetan texts don’t seem to use paragraphs at all. The text is simply divided into pages and lines. I guess traditional Tibetan typography doesn’t use paragraphs. I’ve inserted paragraphs that correspond to the page breaks, but we will have to seek feedback as to whether that works. I may have inadvertently broken the text across sentences. If so, we’ll simply have to have each text be one big paragraph. Or introduce our own paragraphs, I guess.

One further detail on font subsetting:

In Source Sans Regular, add the metrical glyphs, and also the “Open Book” glyph.

I’ve tried adding this on Font-Forge, but it doesn’t even recognize the Unicode range. So that is impressively obscure! Hopefully it can be inserted with the subsetting tool you use.