Skip to content

perf: self-host the webfonts, drop the render-blocking font chain - #4

Merged
nicolas-maman merged 1 commit into
mainfrom
perf/self-host-fonts
Aug 2, 2026
Merged

perf: self-host the webfonts, drop the render-blocking font chain#4
nicolas-maman merged 1 commit into
mainfrom
perf/self-host-fonts

Conversation

@nicolas-maman

Copy link
Copy Markdown
Collaborator

Lighthouse flagged ~550 ms of render-blocking and a 259 ms critical path on aether-lang.dev. Both were the Google Fonts chain: every page requested a stylesheet from fonts.googleapis.com, and only once that resolved could four woff2 files start downloading from fonts.gstatic.com. Two extra origins, two DNS+TLS handshakes, and nothing could paint until it finished. preconnect was already in place and it was still 259 ms, because preconnect cannot fix chaining.

The same faces now ship from this origin.

What changed

  • no fonts.googleapis.com / fonts.gstatic.com request at all; the preconnect hints they needed are gone with them
  • the two faces used above the fold are preloaded, so they start with the HTML instead of after the stylesheet resolves
  • 84.9 KiB of latin webfont, down from 131 KiB

Where the bytes went

Two independent findings, both from reading the CSS rather than guessing:

  1. Four of nine requested weight variants were never used. The stylesheet only ever sets 400, 700 and 800. Bricolage 600, DM Mono 500, and DM Sans 500 and 600 were downloaded and never applied.
  2. Bricolage was carrying an optical-size axis the site never asked for. Nothing sets font-optical-sizing or font-variation-settings anywhere, so the opsz 12..96 axis was dead weight: 75.1 KiB with it, 40.3 KiB without.

These are variable fonts, so one file per family covers its whole weight range. latin-ext is declared but stays lazy behind unicode-range, only fetched if a character needs it, so it costs repo size and not load time.

DM Mono bold is unchanged: that family has no 700, so it was already being synthesized.

Not fixed, and why

The cache-lifetime item is not addressable in this repo. static/CNAME is aether-lang.dev, so the site is served by GitHub Pages, which fixes its own Cache-Control and exposes no way to configure it (fly.toml is only the playground backend). The routes would be putting a CDN in front or moving hosting, neither worth it for 7 KiB.

The forced-reflow item (44 ms) is reported as [sin asignación] with no attributed source, so there is nothing to act on yet.

Testing

./test.sh passes in full. Served the tree locally and confirmed all three font files return 200 at the paths the stylesheet resolves to, the stylesheet carries its 10 @font-face blocks, and no page makes an external font request. The url() values are CSS-relative, so they resolve identically from /index.html and from /Docs/*.html.

60 pages plus the gendocs.py template, so regenerated docs keep the change.

Every page pulled three families from fonts.googleapis.com, which meant
a stylesheet request to one origin and then the font files from a second
before any text could paint. Lighthouse measured that chain at 259 ms of
critical path and around 550 ms of render-blocking.

The same faces now ship from this origin:

- no fonts.googleapis.com or fonts.gstatic.com request, so two DNS and
  TLS handshakes and the whole request chain go away. The preconnect
  hints they needed go with them
- the two faces used above the fold are preloaded, so they start with
  the HTML rather than after the stylesheet resolves
- 84.9 KiB of latin webfont down from 131 KiB

The byte saving comes from two things. Four of the nine requested weight
variants were never used anywhere in the CSS (Bricolage 600, DM Mono 500,
DM Sans 500 and 600). And Bricolage's optical-size axis is dropped, which
halves the file, nothing in the CSS sets font-optical-sizing so it was
carrying an axis the site never asked for.

Variable fonts, so one file per family covers its whole weight range.
latin-ext is declared but stays lazy behind unicode-range, only fetched
when a character needs it.

Cache lifetime, the other Lighthouse item, is not addressable here:
GitHub Pages fixes its own Cache-Control and offers no way to set it.
@nicolas-maman
nicolas-maman merged commit 4dfe609 into main Aug 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant