Google Fonts の表示最適化

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

## Step1: Google Fonts 導入

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

```CSS
@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');
```

```HTML
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Kosugi&display=swap">
```

WebPageTest での結果です。
![スクリーンショット 2021-03-22 16.05.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131281/570b1f95-fa0c-8e6f-7cbb-a813e054929c.png)
![qii1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131281/a2b1e9bb-82b9-0569-1747-f413f0aa8b09.png)

わざと重く作っていたので、スコアがひどいです。
ウォーターフォール図を見ていて気付くのは、**font.googleapis.com** の読み込みが
２つに分かれてしまっていること。
(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. 日本語フォントのサブセット化

を行いました。

```HTML
<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=公開まで後日時間">
```

![スクリーンショット 2021-03-22 16.05.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131281/4c5f605d-00f2-a407-610d-220e0bcba8c9.png)
![qii2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131281/0d6bb5e3-a9ae-36e7-90a9-7b44d9db3516.png)

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

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


## Step3: dns-prefetch

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

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

```HTML
<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=公開まで後日時間">
```

![スクリーンショット 2021-03-22 16.05.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131281/071852eb-ffc7-c246-8887-d3a0663135b3.png)
![qii3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131281/7f5f4397-3049-3e8c-c9ea-c4953be8a834.png)


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

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

```rel="preload``` とかどうだろうか。。といろいろ調べていて、
[rel=”preload”を極めるために必要な2種類のプリロード機能](https://techblog.raccoon.ne.jp/archives/1575956867.html) の記事に行き着きました。

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

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

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

```HTML
<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>
```

![スクリーンショット 2021-03-22 16.04.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131281/35b46f3e-3f7e-9d91-767b-45c740ed433b.png)
![qii4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131281/24ed685e-8eb8-c335-8c7d-552c67306107.png)

総リクエスト数・転送量が減り、
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から特定の文字列のみのフォントを取得する](https://qiita.com/tkn_e/items/ae3b8890f3642788420d)
こちらで紹介されていました。

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