結論からいうとタイトルのままだがやや正確さを欠いているので正確に言い直しておく。Google Fontsをサイト通り普通に読み込んでいる限り高いPageSpeedとGoogleFontsによるウェブフォント採用は両立できません。あくまで意見であって事実でも真実でもないが正しいと思っている。ちなみにサイト通りの読み込み方法というのは<head></head>内に

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

を記述してfont-family'Noto Sans JP', sans-serif;を指定することを言います。Noto Sansの場合の例です。これがいわゆる「いわれるがままGoogle Fonts」というものです。

Google Fontsとは

Googleが提供するウェブフォントのサービスのこと。ウェブフォントというのは、ユーザ側のフォントの有る無しに関わらず同じフォントのページを配信できる技術のことで、どうやってるかというと単純に逐一フォントファイルを配信することによって実現している。当然、日本語のフォントファイルはサイズが大きいため、そのまま逐一配信するとたとえキャッシュどうこうをやったとしても転送量がモリモリ膨れ上がってしまう。

そこで、ダイナミックサブセットという、いわゆる使う文字のフォントのみを動的に選択してダウンロードさせるという技術でそこをケアしているんだ、というのが一般的なウェブフォントの説明。確かにそれならば転送量はそこまで大きくならなそうだ。ただGoogle Fontsにいわれるがまま指定したCSSの中身を見る限りPDFのフォントサブセット埋め込みのように厳密に使う文字だけを配信(埋め込み)しているわけではなく、unicode-rangeによってざっくりやっている感じになる。そら1文字ずつ送っていたら逆にオーバーヘッドをくらうだろうしキャッシュなんて効きそうもないしGoogleがこうしているんだからこれが最善なのだろう。

それでもNoto Sansのように文字化けしないことを売りとしている多言語対応の大きなフォントファイルにおいては転送量の面で十分な恩恵がありそうだ。一方でこのサブセット方式は@font-faceごとにunicode-rangeを書きまくっているので、後にわかる通りCSSそのもののサイズが大きくPage Speed Insightsに怒られます。

逆にメリットは何なのかというと統一的なルック&フィールのページを配信できること。もはやfont-familiyに訳の分からんフォント名を並べて順番に苦悩することは無くなる。転送量と時間さえかければ全てのデバイスで同じタイポグラフィのページを表示することが出来る。そんなウェブフォントの中でもなんとなく安定でありそうな感じがするGoogle Fontsというウェブフォントサービスがなんとなく普及してきている気がしなくもない。

Page Speedという泥沼

Page Speed Insightsというウェブページのスピードを測定する、同じくGoogleのサービスがあるのだがこれが泥沼。Google Fontsを、「いわれるがままの方法」で使っているウェブページをこれに通すとCSSの読み込みが重いということで怒られる。なぜ怒られているのかを整理してみる。

まず見ての通りGoogle Fontsでは、@font-faceが定義されたCSSを読み込むところから始める。次に、その@font-faceにあるunicode-rangeとurlに従ってwoff2形式のフォントファイルが読み込まれる。このCSSの内容は、fonts.googleapis.comからCDN的な感じで動的に取ってくるのだが、この中身は定期的に更新されているようなのでこれをあらかじめpreloadさせておくことはできない。正確には定期的な更新が自動的に反映されるという機能を諦めない限りできない。実際中身を見てみるとそんな感じはする。そこで必ず行われる対策がpreconnectだ。

<link rel="preconnect" href="https://fonts.gstatic.com/">
<link rel="preconnect" href="https://fonts.googleapis.com/">

preconnectは、preloadと違って「何がダウンロードされるかはわからないが、どのドメインにキーリクエストが送出されるかはわかっている」という状況において事前にドメインに対してTCP/IP/HTTPSコネクションを確立しておく新しめの機能。当然ながらPage Speedに怒られるよりも前にこの対策はやっている。preconnectはあくまで「接続するだけ」で実際にダウンロードするわけではないので当然だろう。ダウンロードが始まるのは実際にCSSを読んでから。さらにunicode-rangeが指定されていることを踏まえるとページの<head></head>だけでなく<body></body>まで読み進めて現れる文字コードも調べる必要がありそうだ。このままでは実際にテキストが表示されるまで時間がかかり過ぎる。これはフォント読み込みの間代替フォント、この場合はsans-serifを表示させるfont-display: swap;を指定してFirst Contentful Paint、FCPに影響がないように普通対策する。「いわれるがままGoogle Fonts」のデフォルトなので既に対策済みである。

これの何がPage Speed Insight的に気に食わないのか。実はそもそも最初のCSSのサイズが大きい。理由は先述の通り、また人の目で見てわかる通りunicode-rangeを書きまくっている。ついでに使わないfont-weightまで@font-faceで指定している。いわれるがままGoogle Fontsでフォントを表示してGoogleのサービスでページスピードを計測するとこのCSSの読み込みが遅いので改善しろという提案がなされるのである。使っていないスタイルがあるので削除することを提案されるがそれは君たちが読み込ませたものだ。あらかじめCSSから使わないunicode-rangefont-weight@font-faceを削除しておいたものをサーバに配置してpreloadといったことは先に述べたように定期更新の追従を諦めない限りできない。

Page Speed Insightsの悪魔

だったらもう成す術が無いのかというとそうではない。CSSそのもののロードが遅くてswapが効かないなら、そのCSSをjsで遅延読み込みしてまずはとにかく代替フォントを表示させればFCPという意味では改善されるだろう。しかし考えてみてほしい。そうまでしてFCPを上げることに何の意味があるんだろうか?そこがPage Speed Insightsの泥沼であり悪魔なポイントだと思う。

実際にはフォントに関してこれ以外にもっとやりようは色々あるだろうが、過度にPage Speed Insightsのスコアを追い求めることに対する意見と捉えてほしい。

人間はページスピードというような指標が測定できるとなると、過度にそれを追い求めたがる性質にある。確かに極限までパフォーマンスを改善するという姿勢はエンジニアとして素晴らしいことだが、FCPという指標のみに取りつかれることは悪魔に取りつかれているともいえないだろうか?非常に一般的な話として遅延というアプローチは問題を先延ばしにしただけでなんの解決にもなってない。遅延以外にも問題の解決にはなっていない場合は考えられるだろう。

ここでいうGoogle FontsとPageSpeed Insightsの提示するFCPの両立をCSSの遅延読み込みで行ったところで、単に代替フォントが一足先に表示されるだけで最終的にそのリクエストに関してクライアントに求める転送量や処理量は違いが無いし、多分遅延させたことによってスレッド的なリソースは多く食う。近いうちにフォントのロードが終了してFOUT的なのが発生するコンテンツをほんの少しだけ早くユーザに見せて何の意味があるのか?そんなん絶対に見ずらいに決まってる。だってFlashはどっちにしろするんだから(ちなみにいわれるがままGoogle Fontsでフォントを指定しすぎているサイトをモバイルから開くとフラッシュが頻発してすぐわかる)。もっとも、実際にはこの少しでユーザの離脱率直帰率なんかが変わってくるからスピードの改善が重要であるというのはGoogleの主張するところでありユーザ側の視点からしても遅いサイトはすぐに離脱したくなる。

画像なんかに関してはそりゃプレイスホルダーだけ先に出して後から出てきてもまあ許せるしスクロールしなきゃ見えんところにある奴なんかに関してはよりごもっともだけども。スクロールしないと文字が1つも見えないページとか無いやろう実際。非同期はともかく遅延はフラッシュの回数を変えることが無いから意味がない(非同期はキャッシュも込で先に終わってればフラッシュはしないはず)

単なるトレードオフだから諦める

悪魔から解放されよう。我々はウェブフォントを導入したことでInsightsのスコアは低下させたかもしれないが、統一的なフォントでページを配信するということを達成している。無意味なfont-familyの順番問題からも解放された。しかも「いわれるがまま」コードを2つほど挿入するだけの超簡単な方法で何の手間をかけることもなく。それは単なるトレードオフでもともと両方取りは出来なかったということだ。Insightsを騙すような方法で無意味にFCPを追い求めることはやめて正々堂々とメインスレッドでGoogle FontsのCSSを読み込ませよう。それでInsightsのスコアが低くなる以外の問題があるだろうか?

ウェブフォントは思ったよりページを重くしないというのは、ウェブフォント界隈で良く言われていることであるし、実際自分のユーザエクスペリエンスはウェブフォントによってそこまで低下していない。自分の環境ならモバイルでもInsightsのラボデータほどFCPは遅くない。だからGoogle FontsとInsightsスコアの両立はいさぎよく諦めよう。少なくとも「いわれるがまま方式」は簡単というのも込である意味最適であってCSSの遅延読み込みはこの場合はミスリードだと思う。

サードオプション

このページは1度書き直している。というのもやっているうちに意見が多少変わったからだ。ただCSSの遅延読み込みがミスリードであるということは変わっていない。何かを諦めなければこれ以上Page Speedは改善されないというところも同じだ。新たな知見は諦めるべきものは何かをもう少し考える必要があったということ。

定期更新の追従である。これを強調するように書き直してきた。良く考えると、これを諦めるべきか否かは更新の頻度や内容を知らないことには判断の下しようもないだろう。仮にこの更新が半年おき、内容が軽微なものだったらどうだろうか?隠れたメリットとして重要コンテンツであるフォントファイルをおそらく誰の自サーバよりも強くて速いGoogleサーバから落とさせている点があった。これも得られるメリットと比較して再考に値するだろう。サードオプションはgoogle webfonts helperによるホスティングであった。

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