Google Fonts の表示最適化


Google Fonts についての最適化をちょっと考えてみました。
計測環境の揺らぎがあるかもしれないけど、
最適化によって効果が見えたのでまとめます。

Step1: Google Fonts 導入

サブセット化も、何も考慮していない状態です。
読み込みは比較のため CSS 内に @import の読み込みと HTML の link 要素の2つの読み込みにしました。

@import url('https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@300;400;600&display=swap');
@import url('https://fonts.googleapis.com/css2?family=DotGothic16&display=swap');
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Kosugi&display=swap">

WebPageTest での結果です。

わざと重く作っていたので、スコアがひどいです。
ウォーターフォール図を見ていて気付くのは、font.googleapis.com の読み込みが
2つに分かれてしまっていること。
(4) の読み込みは、 HTML 内に link 要素で記述したものでした。
(19)(20)の飲み込みは、一度 style.css を読み込んでからその中で
@import で取得したファイルです。

(19)と(20)の CSS 取得が終わるまで DOM Content Loaded が始まりません。
昔、よく「パフォーマンスが悪くなるから CSS に @import を使うな」と
言われていましたが、その問題がはっきり出ています。

Step2: HTML 内の呼び出し、日本語フォントのサブセット化

step1 の反省を踏まえて、

  1. font.googleapis.com の呼び出しは HTML 内にする
  2. 日本語フォントのサブセット化

を行いました。

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@300;400;600&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Kosugi&display=swap&text=タイムライン">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=DotGothic16&display=swap&text=公開まで後日時間">


他にもアセットの最適化などを行っているので、だいぶスコアが改善しました。
Core Web Vitals もオールグリーンになりました。

注目したいのは fonts.gtatic.com というフォントデータの通信がかなり減ったことです。
Google Fontsは日本語ファイルを細切れにスライスしてHTTP/2で配信 の記事にある通り、
Google Fonts はサブセット化しないでそのまま使おうとすると、
ファイルがいくつか分解されることがあります。
サブセット化によって、ファイル分割がなくなり、取得ファイル数・データ量とも減らすことができました。

Step3: dns-prefetch

fonts.googleapis.comfonts.gtatic.com に対して dns-prefetch を行いました。

preconnect でも良いかと思ったのですが、IE と Firefox 未対応なので
念のため dns-prefetch にします。

<link rel="dns-prefetch" href="//fonts.googleapis.com/">
<link rel="dns-prefetch" href="//fonts.gtatic.com/">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@300;400;600&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Kosugi&display=swap&text=タイムライン">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=DotGothic16&display=swap&text=公開まで後日時間">


少し改善したかな。。。?
先に fonts.gtatic.com の DNS 解決したことにより、
DOM Content Loaded 後のフォントデータの読み込みが少し速くなっています。
Total Blocking Time(初期表示からページが操作可能になるまで)が
少し改善したのはこの影響かもしれません。
Cumulative Layout Shift (レイアウトのかくつきスコア)が
改善するかと思ったのですが、そこは変わりませんでした。

Step4: 自前サーバでフォントを配信

rel="preload とかどうだろうか。。といろいろ調べていて、
rel=”preload”を極めるために必要な2種類のプリロード機能 の記事に行き着きました。

link 要素での読み込みは preload scanner が使えるので、
preload を使う必要はないと思っていたのですが、
現在 fonts.googleapis.com から読み込んでいるフォントは
サブセット化できる(動的でない)ので、フォントデータを自前サーバに置き
それを preload すればもう少し改善できるのでは?
と思いつきました。

Google Fonts で使っているフォントのライセンスを確認し、
今回使っているフォントは自前サーバにおいても問題ないと判断しました。

サブセット化された woff2 のデータをダウンロードし、自前サーバにアップします。
それを HTML から preload で読み込みます。

<link rel="preload" href="./fonts/josefinsans.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="./fonts/DotGothic16.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="./fonts/Kosugi.woff2" as="font" type="font/woff2" crossorigin>


総リクエスト数・転送量が減り、
DOM Content Loaded より前にフォントデータが読み込まれたことで
Total Blocking Time が改善!
Cumulative Layout Shift もわずかに良くなりましたが、
preload のおかげか転送量が減ったためなのかは、わかりませんでした。

まとめ

  • フォントが静的に配信できるなら Google Fonts の自前サーバ配信がいい。
  • 動的な場合は dns-prefech が限界かも
  • サブセット化をすると日本語フォントの場合総リクエスト数・転送量が減る
  • Google Fonts の読み込みは CSS よりも HTML 内で行った方が良い
  • IE は preload が使えないから dns-prefech まで(woff2 も使えない)

動的なサブセットを Wordpress で作る方法は、
WordPressサイトでGoogle Fonts APIから特定の文字列のみのフォントを取得する
こちらで紹介されていました。

割と普通な着地になってしまったかも。
ご参考になれば幸いです。