Kirki: Google Fonts from CDN

Created on 21 Feb 2019  路  8Comments  路  Source: kirki-framework/kirki

Issue description:

Hey @aristath,

great work on 3.0.36!

One question. I think I'd like to give users the option to chose between Fonts being hosted locally or from Google CDN. Is there a way to accomplish that?

Version used:

3.0.36

Most helpful comment

I'm glad you enjoy v3.0.36 :+1:

The choice to always use locally-hosted googlefonts was a conscious choice... Did a lot of research and experiments, talked to a lot of people in WP's Slack, followed many conversations on wp-core's meta channel (they started doing the same thing there). Even by using preconnect for googlefonts, the CDN is slow. VERY slow.

I don't think I can explain it better than this article: https://medium.com/cloudflare-blog/fast-google-fonts-with-cloudflare-workers-109b16387f48

The way Google fonts are served, the CSS is on one domain (fonts.googleapis.com) and the font files are on a different domain (fonts.gstatic.com). Since they are on separate domains, the fetch for each resource takes a minimum of four round trips back and forth to the server: One each for the DNS lookup, establishing the socket connection, negotiating TLS encryption (for https) and a final round trip for the request itself.

The requests can鈥檛 be done in parallel because the fonts aren鈥檛 known about until after the CSS has been downloaded and the styles applied to the page. In a best-case scenario, this translates to eight round-trips before the text can be displayed (the text which was already available in the browser as soon as the HTML was available). On a slower 3G connection with a 300ms round-trip time, this adds up to a 2.4 second delay. Best case!

In previous versions I was able to cut down the number of roundtrips from 4 to 2 by caching the gfonts CSS and then just getting the actual files from the CDN.
But those 2 roundtrips were still taking their toll and pages became unnecessarily slow.

By locally hosting gfonts, the browser doesn't waste time with extra handshakes and requests, it just gets the files immediately and serves them. And since 3.0.36 doesn't even enqueue a file but instead inlines the styles, it's even faster and everything is non-render-blocking.
It's actually possible to get a 100% pagespeed score now because of these improvements and it was absolutely impossible with previous versions due to the way gfonts work.

Additionally since Kirki can now parse the css for fonts, the new method was able to leverage the font-display property so that text renders even faster.
Put on top of that all the GDPR concerns and doubts that google-fonts inherently have and you'll start to understand why this change was deemed necessary.

Now I _could_ add a filter to allow asyncronously loading google-fonts it would be really easy to do so. The implementation exists and is used in the customizer to live-update the fonts without refreshing the page, it's just a matter of changing a condition and adding a filter.
But what would be the point? Besides the fact that users would have an option, is there really a good reason to do so? (that's a real question btw, if you can think of a good reason besides "user wants a choice because they don't know any better" I'm all ears).

All 8 comments

I'm glad you enjoy v3.0.36 :+1:

The choice to always use locally-hosted googlefonts was a conscious choice... Did a lot of research and experiments, talked to a lot of people in WP's Slack, followed many conversations on wp-core's meta channel (they started doing the same thing there). Even by using preconnect for googlefonts, the CDN is slow. VERY slow.

I don't think I can explain it better than this article: https://medium.com/cloudflare-blog/fast-google-fonts-with-cloudflare-workers-109b16387f48

The way Google fonts are served, the CSS is on one domain (fonts.googleapis.com) and the font files are on a different domain (fonts.gstatic.com). Since they are on separate domains, the fetch for each resource takes a minimum of four round trips back and forth to the server: One each for the DNS lookup, establishing the socket connection, negotiating TLS encryption (for https) and a final round trip for the request itself.

The requests can鈥檛 be done in parallel because the fonts aren鈥檛 known about until after the CSS has been downloaded and the styles applied to the page. In a best-case scenario, this translates to eight round-trips before the text can be displayed (the text which was already available in the browser as soon as the HTML was available). On a slower 3G connection with a 300ms round-trip time, this adds up to a 2.4 second delay. Best case!

In previous versions I was able to cut down the number of roundtrips from 4 to 2 by caching the gfonts CSS and then just getting the actual files from the CDN.
But those 2 roundtrips were still taking their toll and pages became unnecessarily slow.

By locally hosting gfonts, the browser doesn't waste time with extra handshakes and requests, it just gets the files immediately and serves them. And since 3.0.36 doesn't even enqueue a file but instead inlines the styles, it's even faster and everything is non-render-blocking.
It's actually possible to get a 100% pagespeed score now because of these improvements and it was absolutely impossible with previous versions due to the way gfonts work.

Additionally since Kirki can now parse the css for fonts, the new method was able to leverage the font-display property so that text renders even faster.
Put on top of that all the GDPR concerns and doubts that google-fonts inherently have and you'll start to understand why this change was deemed necessary.

Now I _could_ add a filter to allow asyncronously loading google-fonts it would be really easy to do so. The implementation exists and is used in the customizer to live-update the fonts without refreshing the page, it's just a matter of changing a condition and adding a filter.
But what would be the point? Besides the fact that users would have an option, is there really a good reason to do so? (that's a real question btw, if you can think of a good reason besides "user wants a choice because they don't know any better" I'm all ears).

@aristath,

Fair enough! :)

Thanks for sharing all the insights. Appreciate it!

Personally, I like that approach and you're right - it's hard to find a reason to use Google CDN instead.

Hey @aristath,

I'm running a couple tests now and figured you're using font-display: swap; even though the font is being served locally. Is this really necessary? From what I understand, this is causing FOUT on the initial page load (after that, it's being cached).

I think the font-display property would make sense if we were still using Google CDN.
Please correct me if I'm wrong :)

It's a double-edged sword.
If you remove font-display, then google-pagespeed complains and recommends you add it.
With font-display:swap you get FOUT, without it you get FOIT. Some prefer one, others prefer the other. With FOIT on slow connections you have to wait for everything to load before you can start consuming content on a site.
With FOUT you can start reading immediately, and when the font loads it gets replaced with the proper one.
On decent networks the difference is negligible and FOIT/FOUT are literally "flashes". But not everyone is as privileged... For example when it's raining in my area and my network speed drops, it's like I'm reliving the 90's PSTN torture. And FOIT is no longer a "flash of invisible text", it becomes a loooong waiting period (I mean 20s+, I'm actually reliving the 90's) that could be avoided if sites were using font-display:swap.

If however you really do find FOUT annoying and you prefer FOIT & a google-pagespeed rank drop, then there's a filter you can use:

add_filter( 'kirki_googlefonts_font_display', function( $font_display ) {
    return 'block'; // Use auto|block|swap|fallback|optional.
} );

Hey @aristath,

Thanks for your fast reply! :)

I was just about to say that even without font-display: swap; I get the exact same behaviour.
Overall, it's not a big deal as the fonts are being cached anyways after the initial page load.

Pretty much the only alternative would be, to allow users to load the font from Google (again) - even without serving them asynchronously. I think we can both agree that this is not an option considering performance & GDPR.

Thanks again for your feedback! :) I'll play with the different font-display values a little bit.

Have a great day!

Yeah, googlefonts is a bit of a balancing act. If you play with different values, try them using throttling in your browser's dev tools & disabling cache there. It's the only way to actually see how they behave.
Also try testing on google-pagespeed, other services, see which one is best for you.
The current implementation is the best one I've found so far through testing & experimentation... But if you find some other solution that works better than the current implementation I'm open to suggestions :+1:

Hey @aristath, I got a couple users requesting an option to revert back to Google CDN. I totally agree with you on this but also think a filter (just in case) makes sense here.

Is there a filter to load Fonts from Google the classic way (ideally not asynchronously)?

Thanks!

This should do it:

add_filter( 'kirki_use_local_fonts', '__return_false' );

There's also the kirki_googlefonts_font_display filter which can be used in conjunction (see comment above) to change the font-display property.

Keep in mind thought that the gfonts CSS gets cached for 24 hours, so if you want to reset the caches and see the changes immediately you'll need to visit domain.com/?kirki-reset-cache=1 to reset the transients and have the styles get re-generated. :+1:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Vishal-Deshpande picture Vishal-Deshpande  路  3Comments

fakrulislam picture fakrulislam  路  3Comments

rinkuyadav999 picture rinkuyadav999  路  4Comments

manuelmoreale picture manuelmoreale  路  3Comments

allysonsouza picture allysonsouza  路  3Comments