webフォントの軽量化に関してのメモ

いくつか試したのでメモとして。内容は個人の見解なので正解というわけではなく、その点留意下さい。

前提

  • webフォントを使う
  • Google FontsのCDNとダウンロードの2手法を想定
  • 適用するのはコンテンツ全体ではなく一部
  • なるべく軽量にしたい

結論

  1. フォントをダウンロードしてサブセット化し、preloadも使って読みこませるのが最も無駄がなく早い。
    サブセット化の一手間が毎回必要。
  2. GoogleFontsのCDNでtextパラメータを使うと早い。
    記述する手間が必要で、文字数制限に留意が必要。
  3. GoogleFontsのCDNは速度が速く手間もかからない。
    それなりに無駄なダウンロードが発生し、ダウンロードされるファイルの数も多い。
  4. サブセット化もしないでサーバーにフォントを置いて用いるのが最も遅い

結論としては上記のように考えられましたので、webフォント適用対象にクライアントによる変更箇所が含まれる場合、preloadとGoogle Fontsの組み合わせが最も現実的に思います。

クライアントによる変更箇所が含まれない場合、手間はかかるものの制作側でサブセット化する方法が使えるため、Google Fontsをそのまま使うよりも軽量で早い表示が可能です。

続いて詳細を書こうと思ったものの、既に先行で詳しい記事がありましたので以下を参照のこと。

補足

その他調べたこと試したことをメモ的に。

unicode-range

unicode-range は CSS の記述子で、 @font-face で定義されたフォントから使用される特定の文字範囲を設定し、現在のページで使用できるようにします。ページがこの範囲内の文字を使用しない場合、フォントはダウンロードされません。少なくとも 1 つの文字を使用すると、フォント全体がダウンロードされます。

Google Fontsが速度向上策として使っており(読み込ませるCSSを見れば確認できます)、指定したUnicode 符号位置(コードポイント)の文字があった場合のみダウンロードを開始させることができます。

この仕組みだけで目的のフォントだけをダウンロードできれば最良ですが、当然ながらそんな魔法のような便利機能ではなく、前述の引用部分にあるようにすべてがダウンロードされてしまいます。

Google Fontsでは最初から一定のルールに従ってフォントを小さなファイルに小分けしており、ページ内の文字にunicode-rangeに記載した文字があった場合にそのフォントが含まれるファイルだけをダウンロードすることで、なるべく無駄なダウンロードが発生しないような設定になっている模様です。

サブセットフォントメーカー

武蔵野システムさんのサブセットフォントメーカに関しては、macOS Catalinaで使えないという記事が検索で見つかる場合がありますが、現在は対応版をリリースされているので利用可能です。

ちなみにサブセットフォントメーカーはTrueType(.ttf.ttc)、OpenType(.otf.ttc)が対象なので、.woffは対象外です。

そのため対象フォントタイプでサブセット化後に同社のWOFFコンバーターを使う必要がありますが、.woff2など他のタイプへの変更も同時にできます。

Google Fontsのtextの文字数制限

上記に書かれているようにtextパラメーターを設定することで簡易にサブセット化ができ、無駄なフォントをダウンロードせずに済みます。
ただし調べた範囲では以下のような注意点がありました。

  • URLとして成立している必要があるので、文字数が多いと414エラー(URI Too Long)になる
  • おおよそ全角で280文字程度を超えると、textを使わないのと同じ状態になる

URLのパラメーターとして設定するため414エラーは想定していましたが、280文字あたりでtextの意味がなくなるのは想定外でした。

開発者ツールのNetworkなどで試すと、ダウンロードされたフォントの状態がわかるので境目を確認することが可能です。

なお、速度の視点もありますがGoogle FontsのCDNを使う場合、以下のようにブラウザに応じて出力内容を変更するようなので、そういった細かな調整というメリットも含まれていると考えます。

ローカル内の該当フォントの利用

webフォントで指定したフォントと同じフォントがローカルにあり、かつウェイトも同じであれば、webフォントをダウンロードせずにそちらを利用することが可能な模様です。

PHPで指定文字のUnicodeコードポイント一覧を作成する

当初unicode-rangeの動作を勘違いしており、Unicodeコードポイントさえ用意すれば独自にサーバーに入れたフォントでも不要な文字がダウンロードされないのではと考えて試作したのが以下のコードです。
既に書いているように期待した動作にはならないため全くの無駄なのですが、一応メモ的に。ある程度書いた段階で無駄さに気がついたので動作確認はしておらず、問題あるコードかもしれません。


$str       = '変換したい文字列';
$str_array = array();

//指定文字列を一文字ずつ配列に変換
$str_array_size = mb_strlen( $str, 'UTF-8' );
for ( $i = 0; $i < $str_array_size; $i++ ) {
  $str_array[] = mb_substr( $str, $i, 1, 'UTF-8' );
}
//配列内の重複文字を削除
$unique_array  = array_flip( array_flip( $str_array ) );

$unique_array_size = count( $unique_array );
$unique_array      = array_merge( $unique_array );
$codepoint_array   = array();
for ( $i = 0; $i < $unique_array_size; ++$i ) {
  //mb_ord()でコードポイントに変換し、dechex()で16進数に変換し、U+ をつけて配列に入れる
  $codepoint_array[] = 'U+' , dechex( mb_ord( $unique_array[ $i ], 'UTF-8' ) );
}
//配列をカンマ区切りの文字列に変換する
$codepoint_string = implode( ',', $codepoint_array );

return $codepoint_string

mb_ord()がない場合はもっと複雑な処理が必要なようですが、mb_ord()はPHP7.2.0以上なら問題なく使えるはずです。

重複した文字の削除に関しては以下の記事を参考にさせていただきました。
ただ順番が乱れるためかforによる処理がおかしくなったので、array_merge()で整える必要がありました(他により良い方法があるかもしれません)。

結び

個人的には、表示速度とwebフォント反映の問題(FOUT)に関して最も効率がよい解答は以下になるのではと思います。CSSと同様の考え方であり、それ故にCSSと同様に実現困難かと思いますが、CWV(Core Web Vitals/コアウェブバイタル)への対応策としても有効かと思われます。

  • ファーストビュー内の対象文字のみサブセット化してpreloadで読み込み、その他はGoogle Fontsを遅延読み込みで利用する

しかしながら好きな時に好きな様に手を入れられる自前のサイトならいざ知らず、依頼を受けて制作し納品するサイトであるならば、全てGoogle Fontsにお任せというのが現実的な方法に思えます。

第一水準のみをサブセット化するというのも選択肢には入るのですが、クライアントはこちらの想定外の利用を行うというのが常なので、あとで「フォントが一部変だ」となる可能性は高く安心できません。使用文字をあらかじめ制限するというのも現実的ではありませんし。

仮に自前の対策として他の案も検討したとしても、行き着くところは結局Google Fontsと同じようにフォントの分割とunicode-rangeの利用になりそうです。

もっともGoogle Fontsが永続する無料サービスかどうかはわからないので、その点では不安定な土台の上に成り立つ状態ではあり、Google Fontsの利用もいつまで安泰かはわかりませんが。

Core Web Vitalsに関して

既に類似のテーマの記事が出ていますので簡単に。

「webフォントは重い」「webフォントは遅い」という問題はある程度改善されていると言えます。
ファイルを追加で読み込む以上は読み込まない場合に比べて重くならないわけがなく、その点を踏まえて考えれば画像と同様に必要に応じて使用を検討できるレベルに達しているという印象です。

他方ユーザーとして見た際に、swapによるフォント差し替え時の表示やCLS(Cumulative Layout Shift)はそこまで気にされるものではないようにも思います。
画像のように後続要素への影響が特別大きなものでもないですし、フォント反映時の一回のみでしかCLSは発生しませんので。

加えて条件次第になると思いますが、webフォントの適用前後で大きく高さが変化しない可能性もあります。
実際に試しましたが、実験ではレイアウトシフトが発生しても微量だったためPageSpeed Insightsで合格点は取れました。

「レイアウトシフトが0でないと夜も眠れない!」という方でもなければ、ツールが許容する範囲を確認しつつ実装することでwebフォントを本番でも使えるのではと思います。

その他参考資料

5人がこの記事を評価

役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。

連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。

コメント欄