Before tackling how, why might you want to self-host?
Caching
Google’s CDN serves CSS with a short (24-hour) cache header. This means daily visitors to your site will likely have to wait for a round-trip to the CDN before your text renders.
$ curl -i 'https://fonts.googleapis.com/css?family=Roboto'
…
HTTP/1.1 200 OK
Cache-Control: private, max-age=86400
See also, related typekit post: regarding-the-flash-of-unstyled-text-in-chrome
Smaller font files
You may be getting larger fonts than you actually need. If you’re only using the font for a fancy header, or some static text like a website name, the smallest character set – latin – is probably overkill.
The unicode range field here shows what’s included:
@font-face {
unicode-range: U+0000-00ff, U+0131, U+0152-0153, U+02bb-02bc, U+02c6, U+02da,
U+02dc, U+2000-206f, U+2074, U+20ac, U+2122, U+2212, U+2215;
}
Visualised with fontforge:
I find you can get away with a ~50% size reduction for English-language text by
restricting to ranges 20-7E,2013-2014,2018-19,201C-201D,2022,2026
. I know for
sure I’m never going to need the copyright symbol…
Privacy, availability
The privacy aspect’s somewhat contentious, and boils down to whether you trust Google’s word on what they do (and will do in the future) with the collected data. This stackoverflow issue discusses the main points.
Regarding availability: if you have users in China, you’ll want an alternative solution, as Google web properties are often blocked.
So, onto how…
Self-hosting
First off, snippets like the above @font-face
definition might give the
impression that self-hosting fonts is complicated; but it’s really not. Assuming
you’re only interested in dealing with “modern” browsers, there’s only two file
formats to worry about - woff
, and woff2
. Woff2 is just a compressed form of
woff, so generating it’s not going to introduce complications of the sort that
generating svg
from ttf
might.
In summary, you need two things:
- An
@font-face
definition that points to your font in its various weights, styles and encodings. - A set of font files, hosted on your server.
The excellent google-webfonts-helper site will generate those files for you, assuming you’re happy with one of the default character sets.
If you want to optimize those further, you need to look into subsetting the font to remove unwanted characters.
One possibility for this is to use the python fonttools
package:
pyftsubset font.ttf
--output-file=font.woff2
--flavor=woff2
--unicodes=U+20-7E
There’s also a load of JS-based solutions, some of which integrate with webpack.
I tried font-subset-loader which in turn uses fontmin
, but ran into an
issue with whitespace getting mangled.
Ordinarily I’m a big proponent of being able to build everything with a single command, but the maintenance overhead and additional compilation time for JS-based solutions didn’t seem worthwhile, given how infrequently fonts are going to change.