👋

Next.jsのFont Optimizations(Webフォントの最適化)を試してみる

2020/12/29に公開

追記) v10.2からデフォルトでGoogle Fontsの最適化が行われるように

Next.js v10.2から自動でWebフォントの最適化が行われるようになりました。v10.2時点ではGoogle Fontsにのみ対応しているとのことです。特に設定は不要で、いつも通りGoogle Fontsを読み込めばOKです。

↓ 詳細

https://nextjs.org/blog/next-10-2#automatic-webfont-optimization

これより下の解説は古い内容になります。実装の参考にしないようお願いします。


以前、Next.jsのリポジトリを眺めていたときにFont Optimizationsというプルリクエストを見つけました。

2020年12月時点ではExperimantalな機能のようですが、v10.0.4で既に使えるようになっていたので試してみました。

:::message alertz
Next.js v10.0.4でのドキュメントに則っていない記録になります。
:::

Font Optimizationとは

まだドキュメントに説明が書かれていないので、プルリクエストの説明文を引用します。

...略... we will grab the <link rel='stylesheet' href='https://fonts.googleapis.com/...'/>(List of font providers to be extended in future PRs) tags and inline it's content.

出力されたHTMLの中からWebフォントのスタイルシートを見つけて、その中身をインラインで展開してくれるようです。今のところはGoogle Fontsに対応している模様。

This eliminates the extra round trip that the browser has to make to fetch the font declarations. This helps in faster paints and improved LCP.

ものすごくざっくりというと、フォントデータのフェッチ時間を節約できるため表示の高速化が期待できるというわけです。上の文章に書かれている「LCP」はLargest Contentful Paintの略ですね。

どのような仕組みで実現されているか

以下もプルリクエストの引用です。

  1. Gathering the used <link rel='stylesheet' href='https://fonts.googleapis.com/...'/> tags and downloading their content at build time.
  2. Replacing the inspected Link tag with a style tag and the content of the href inlined within this style tag at serve/render time.
    In order to do the above-said we use.

ビルド時にhttps://fonts.googleapis.com/...から始まるスタイルシートの読み込みタグを見つけて、その内容をすべてダウンロードするようです。WebフォントをCDNから読み込むより、セルフホストの方がパフォーマンスが良いとされているので、嬉しいですね。

参考

と思いきや、実際に試してみて分かったのですが、フォントのデータ(◯◯.woff)自体はFont Optimizationを使ってもGoogleのサーバーから読み込むようです。今後woffもダウンロードしたりするのかな?

Font Optimizationのより詳しい仕組みはプルリクを読んでいただくのが良いと思います。

実際に試してみる

HeadでGoogle Fontsを読み込む

では実際に試してみたいと思います。コードを見る限りnext/headタグ内に配置された<link>が対象になるようです。というわけで_app.tsxでGoogle Fontsを読み込みます。

_app.tsx
import Head from "next/head"

...return (
  <Head>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@700&display=swap" />
  </Head>
)

next.config.jsでFont Optimizationを有効化

v10.0.4時点ではexperimental内で指定する必要があります。

next.config.js
module.exports = {
  experimental: {
    optimizeFonts: true,
  },
};

たったこれだけで準備完了です。

デプロイして確認

デプロイしてみると、ちゃんとGoogle Fontsが適用されているようです。ソースを見るとGoogle Fontsの<link>タグがhrefではなくdata-hrefになっていることが分かります。

またdata-hrefの中身(=https://fonts.googleapis.com/...の内容)がstyleタグに展開されています。

上の画像を見ていただくと分かりますが、フォントのデータ自体はhttps://fonts.gstatic.comを読みにいっています。これは通常通りにGoogle Fontsを読み込んだときと同じです。

Font Optimizationの効果は?

Lighthouseで計測してみました。そんなに変わらんやろと思ってたところ……

Font Optimizationなし

Font Optimizationあり

えっ…………
そんな変わる?

「First Contentful Paint」や「Total Blocking Time」が1秒近く短縮されています。ブラウザのキャッシュを無効にして読み込むと、たしかに体感速度的にも少し早くなっているような…?

おわりに

Font Optimizationはかなり有益な機能だと思います。さらに.woffデータ自体も設定不要でセルフホスティングできるようになれば最高ですね。
(VercelにデプロイしたときにBandwidthを消費しまくって、プランをひとつ上げる必要が出てくるかもしれませんが)

ちなみに
今見ているZennではすでにFont Optimizationが有効になっています。

Discussion