🤔

Astro Fonts APIの挙動を確認してみる

に公開

Astro 5.7

https://docs.astro.build/en/reference/experimental-flags/fonts/

Astro 5.7.0で、Experimental fonts APIが追加されました。
Experimental(実験的機能)なのでまだ正式リリースではありませんが、現状での動作を確認してみます。

概要

ざっくり言うと、Google FontsやAdobe Fonts等の読み込み設定を楽にしてくれる仕組みです。
後述しますが、Next.jsを触ったことがある方は同様のFont Optimization(next/font)という仕組みがあるのでイメージしやすいかと思います。

何が起こるか

具体的な使い方はドキュメントもあるので割愛するとして、Noto Sans JPを読み込んでみましょう。
事前準備として astro.config.mjs に以下のように設定します。

astro.config.mjs
export default defineConfig({
  experimental: {
    fonts: [
      {
        provider: fontProviders.google(),
        name: "Noto Sans JP",
        cssVariable: "--font-noto-sans-jp",
      },
    ],
  },
});

もちろん複数読み込む事も可能ですし、オプションでウェイトやスタイルの絞り込み、unicodeRangeの指定なんかもできるようです。

あとは読み込みたいLayoutやコンポーネントで

<Font cssVariable="--font-noto-sans-jp" preload />

と書くことでプリロードリンクが出力されます。
コンポーネントはどこに書いても良いので、ページによって読み込むフォントを変えることももちろん可能です。

出力されたコードを見るとわかるように、Fonts APIは astro.config.mjs で指定されたフォントをビルド時に /_astro/fonts/ 以下にダウンロードしてくるので、結果的にこのAPIを使うことでフォントファイルの読み込みはGoogle Fontsからではなく同一ドメインから行われるセルフホスティングの形になります。
これによって、他ドメインへのリクエストが減る分ページ読み込みパフォーマンスが微増する可能性、GDPRなどのプライバシー規制への対応にもなる等のメリットがあると言えそうです。

残念な点

実際に動作しているページを用意しました。

確認してみると分かるのですが、Noto Sans JPのファイルを全て読み込んでおり、その結果「吾輩は猫である」というテキストしか無いにも関わらずフォントだけで6MB近い転送が発生しています。
Google Fontsは通常、日本語のような文字数が多いフォントに関してはそのページで使用している文字を動的に判断し、なるべく必要な分だけのフォントデータを送信するといった最適化が行われます。
欧文フォントの場合は気にしなくて良い程度かもしれませんが、日本語フォントを使用する場合は受信するデータ量が本来の使い方より増えてしまう可能性があります。

サイト全体が静的コンテンツで構成されていてcms等から記事を更新する必要が無い場合は、configでunicodeRangeを指定し読み込むフォントを絞り込む、という事も可能そうですがわざわざそこまでするメリットは薄いかもしれません。

余談:Next.jsとの比較

冒頭で少し触れたNext.jsの同様の機能はこの辺にも配慮されています。
ビルド時にフォントをダウンロードしてきて /_next/static/media/ 以下にキャッシュする所までは同じなのですが、cssを出力する際にunicodeRangeで細かく細分化されなるべくそのページに必要なフォントデータしか読み込まないという、ネイティブの使用方法に近いUXになっています。

同じ状態をNext.jsで再現した物が以下の状態で、リクエストされているフォントデータも転送量も最低限に抑えられていることが分かります。

注意点

Astro Fonts API、Next.jsのnext/font共通している事として、対象のフォントファイルをプロジェクト内にダウンロードしてセルフホスティングする形になるというのは 何が起こるか でも書いた通りなのですが、これはサイトの規模やアクセス数によってはデメリットになる可能性があります。
通常、Google FontsのCDNが担うはずのフォントファイルの配信負荷が自身のサーバーにふりかかることになるため、転送量が増加する可能性があります。
残念な点 にあるように、現状Noto Sans JPを設定すると1回アクセスするだけで全ての文字を使っていなくとも強制的に6MB近くのフォントがプリロードされるので、これがそのままアクセス数に掛け合わされてしまう形になります。

まとめ

特に直接的な競合というわけでは無いNext.jsと比較するのは少し意地悪な気もしますし、そもそもまだExperimentalなのでこれからもっと改善されるかもしれないのであくまで現時点の話ではありますが、欧文ベースのシンプルなサイトであれば効果的であるものの日本語フォントを使う場合はデメリットの方が大きくなる可能性があるため、導入は慎重に。

何か見落としや勘違いなどあればご指摘ください。

Discussion