Self-HostなGoogle Fontsを使ってPage Speedに怒られないようにする

2019-12-10 00:062019-12-10 00:20

ウェブフォントによってフォントファイルごとWebページを配信することによって統一的な見た目のコンテンツをユーザに提供できる。これによって昔によくやりがちだったfont-familyによく見た目も知らんフォントを並べてその順番をどうしようかと考える必要がなくなる。見た目を知らずにこれを書いている人結構いるだろというあるある。Google Fontsはそのウェブフォントサービスの1つである。

<link ref="https://fonts.googleapis.com/css?family=Noto+Sans+JP&display=swap" rel="stylesheet"> 

<head></head>内で指定して自分のCSSのfont-familyなんかで'Noto Sans JP'を書いておくだけの超絶お手軽仕様。ここで上げたURLはGoogle Fontsの公式でポチポチやるだけで勝手に教えてくれる。

この方法でページをGoogle Fontsを読み込ませるとPage Speed Insights、以下PSIにフツーにちょっと怒られることをGoogle Fontsを使う限りPage Speedは上がらないでは述べた。やっているうちにgoogle webfonts helperを使ってSelf-Hostedなウェブフォントで重量級の日本語フォントをpreloadすることが最もよいやり方(ベストプラクティス)であると気づいた。方法とその理由を早くいいたい。どっちを先にするか迷ったがまずは方法から。あるあるを早くいいたい~。

Google Fontsをホスティングする方法

google webfonts helper

というサービスを使う。あくまでヘルパであってこれが無いとできないわけではないがこれが無いと限りなくめんどくさい。このサイトがやってくれることは

  • Google Fontsに指示されたCSSを読んでフォントファイルのURLを取得
  • ウェイト単位でunicode-rangeを統合、各ウェイトに対応するフォントファイルを生成
  • 指定したウェイト、コードセットのフォントファイルをzipにまとめてダウンロードさせる
  • Google Fontsによる@font-faceの記述をコピペさせる

といったところ。指示されたCSSを自分で開いてみるとこのへんの想像がつく。1つのフォントに対して複数のフォントファイルが存在するのは異なるfont-weightunicode-rangeごとにフォントファイルが用意されているから。指示されたCSSの内容は頻度はしらんが更新されているようなので生成したフォントファイルが毎回のリクエストで使いまわされている場合は最新版でない可能性がある。

googlewebfontshelperのスクリーンショット1

googlewebfontshelperのスクリーンショット1

  1. 左のサイドバーから使いたいフォントを選択。
  2. そのフォントで表示したい文字コードセットを選択。日本語フォントならばjapaneseにチェック、欧文フォントを別に指定する場合はlatinのチェックは外すほうがよい。指定しない場合チェックを外すと欧文はsans-serifになる。
  3. 使うウェイトを選択。regularと必要に応じてboldの700を選択する。
  4. @font-faceをコピーして自分のCSSのどっかに貼り付ける。Best Supportは最も多くのブラウザをケアできる書き方、Modern Browsersは簡素な書き方でほとんどのブラウザをケアできる書き方。Modern Browsersをオススメする。
  5. ダウンロードボタンを押してzipを落とす。サーバに配置。デフォルトでは../fonts/に配置することになっているが@font-faceをコピペするときにテキストボックスでディレクトリを指定できる。
  6. font-familyに最初に選んだフォント名を指定する。欧文フォントを別で用意する場合はLato, 'Noto Sans JP', sans-serif;を書いてそれぞれのフォントファイルを正しい文字コードセットで配置しておく。

これでSelf-HostなGoogle Fontsが完成する。

ページスピードのための最適化

ここまでは普通にhelperを使ってGoogle Fontsをホスティングしただけ。いわゆる普通のミートスパゲッティ。ここからがマグマなんです(なにがやねん)。ホスティングするメリットを最大限引き出せるので必ずやるべきといえる。

font-display:swap;を書く

書いてください。以上です。これがgoogle fonts helperのデフォルトで無いのはほとんどバグです(何かそうしていない事情があるんでしょうか?教えてほしい)。Google Fontsではデフォルトになっているので。

重量級ファイルのpreload

<link rel="preload" as="font" type="font/woff2" href="/fonts/noto-sans-jp-v24-japanese-700.woff2" crossorigin>

このようにして配置したフォントファイルはunicode-rangeが統合されているのでサイズが大きいです。このままではページのあるべきフォントでの表示時間に影響を与える可能性があるのとPSIをごまかすためにpreloadします。preloadすべきフォントファイルは@font-face内にかかれているものから選択することになりますが何をpreloadさせるかについては次を考慮します。

  • ローカルにない可能性が高いフォント:ユーザのローカルにフォントがある場合はWebからフォントファイルをダウンロードさせるよりもローカルのものを使った方が確実によいです。指定されたフォントファイルがどのローカルのフォントに対応するかは@font-faceを読むまで判断できないはずなので、preloadはブラウザの挙動にもよりますがおそらくローカルにあってもダウンロードされてしまいます。ローカルにありそうなフォントはpreloadさせないようにしましょう
  • コンテンツ内で確実に使用されるフォント:preloadしたのにページで使用しない場合にはブラウザのインスペクタやInsightsで警告が出る場合があります。例えばウェイト700がほとんど出現しないサイトならばそのウェイトのpreloadの必要性は薄くなる。
  • フォントファイルのサイズが大きいか:欧文フォントなどはそもそもフォントファイルのサイズが小さいのでdisplay:swap;だけで十分と言えます。preloadする前にディスプレイswapを書いた時点でファーストペイントの裏でフォントファイルがダウンロードされます。

一般的に書きましたが結論は日本語フォントpreloadの欧文フォントは何もしないのがよいでしょう。ウェブフォントを使っている時点で日本語はローカルにないフォントを使う場合が多いでしょうし。欧文はRobotoなどはAndroidにそのまま入ってるなんかありますしpreloadせんくていいでしょう。

フォントファイルはキャッシュさせる

これについては文句のでようもなくやったほうがいいです。やり方は別ページにゆずりますが静的ファイルのTTL(time-to-live)は長めに設定しておきましょう。個別に設定できるならフォントファイルだけ300日などにしておいても良いでしょう。バージョンアップするとv24のところの名前が変わるので事実上無限大でもいいくらいです。

Google Fontsをセルフホストしたほうがいい理由

したほうがいいといっていますがまずはしない方がいい理由から。つまりデメリットですね。

  • フォントファイルのロードが遅くなる:普通はGoogleのサーバの方が転送速度なんかの面でパワーが強いので予めGoogleサーバにpreconnectしておいた状態でロード時間を比較するとおそらく負けます。
  • フォントのバージョン更新が手動になる:先ほどのスクショにlast modifiedの項目があるようにGoogle Fontsは日々更新されています。セルフホストするとヘルパでダウンロードしたときのバージョンで止まったままになります。
  • 全ての文字が含まれたフォントファイルがダウンロードされる:unicode-rangeごとにダウンロードさせていたものを統合してダウンロードさせるのでページのコンテンツによっては最終的な転送量が大きくなります。

ぐらいでしょうか。つまり言いたいことはデメリットが多くありません。くわえて、これらは条件をつければ一概にデメリットとは言えません。得られるメリットを考えてみます。

  • CSSのサイズ削減:unicode-rangeなどが大量に書かれたCSSはサイズが大きく、それ自体がPSIに怒られていましたがヘルパによってフォントを統合し、使う分だけの@font-faceにしたことによりPSIに怒られません。
  • フラッシュの回数が減少:unicode-rangeに対して1つのフォントファイルをダウンロードさせると、ブラウザにもよりますがそれぞれのフォントファイルのダウンロード完了時に代替フォントからそのフォントへ表示か切り替わるフラッシュが発生します。統合することにより発生するフラッシュの回数は減少します。
  • 必ずキャッシュヒットする:これについても、フォントファイルを統合したことにより初回にページを開いたときの転送量は増えてしまいますが2回目以降は特にpreload指定されているフォントファイルは大抵キャッシュからとれるので長期的に見たときの転送量は大して増えません。必ずは言い過ぎなのでキャッシュヒット率が高くなるが正確でしょうか。
  • バージョンアップに対して安定:バージョンが固定されることはデメリットに上げましたがこれはメリットでもあります。現状のページの見た目に問題が無いならばGoogle Fontsがいくらアップデートされようがページの見た目はいつでもそのままで安定です。ありえないでしょうがGoogle Fonts側の改悪により突然文字化けしたりレイアウトが勝手に崩れるといったことがありません。
  • 複数フォントを使用する際に不要な文字コードセットの@font-faceを書かなくていい:ホスティングしない場合にはどんなfont-familyが来てもそのフォントの存在するタイプフェイスを表示しようと試みていました。ここではfont-familyがわかっていて最適な@font-faceと必要なフォントファイルを配信できるので健康です。

以上がまーあげられる理由でしょう。ページスピードの観点では「仕様していないCSS」「ページ表示に必要なリソース数」の面では確実に有利になります。preloadで大きなフォントファイルを非同期化しておけば大きなフォントファイルについてはPSIに怒られません。結果として実際はどうあれPSIのスコアはホスティングすることで確実に上がります。

さらっと書いたフラッシュの回数ですが、これは人間の感覚で有意にわかります。パパパッと一瞬過ぎてわからないくらいの違いしか無いと想像されそうですが、ホスティング前のフラッシュの回数が明らかに多いです。特にモバイルだとfirefoxの読み込みゲージが左から右に行くにつれて幾度となくフラッシュしたのちにページが表示され、これはエクスペリエンスとしては良くないです。ホスティングした場合は体感のフラッシュは1回だけで、別に代替フォント(そのシステムのsans-serif)の見た目も大抵の場合そんなに汚くないので確実にホスティングのウェブフォントのサイトの方が見やすいです。2回目以降はフラッシュすらしません。デフォルトではキャッシュにヒットしないフォントはダウンロードされるので2回目以降もフラッシュの可能性があります。

まとめ:Google FontsをSelf-Hostしよう

ここまで述べてきた内容はちゃんとデモンストレートするならブラウザのインスペクタ使って比較したいところですがそんなに大きくは外していないでしょう。総合的にみてGoogle Fontsを使用するならホスティングによる方法がベストプラクティスだといえそうな気がしないでもない(何が言いたいねん)。もちろん<head></head>しかいじれない媒体を使っているなどそれができない状況も考えられるのでGoogle Fontsの提供方法がそもそも悪いとは言えません。