O hirunewani blog

AstroではGoogle Fontsを直接利用しない方が良いかもしれない

Created at

Astroはstylesheetを巻き上げてしまうため、preconnectなどの指定より前にGoogle Fontsの読み込みが開始されパフォーマンスが悪化する可能性がある。

Astroがstylesheetを巻き上げる

デプロイ後のサイトで、各ページの初回アクセス時に<link rel="stylesheet">要素が全てhead要素の先頭に巻き上げられる挙動を確認した。

初回アクセス時とリロード時で、次のようになっていた。

初回アクセス時:

<!DOCTYPE html>
<html lang="ja">
<head>
  <!-- Some Comment 1-->
  <!-- Some Comment 2-->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap">
  <link rel="stylesheet" href="/_astro/some-styles.css">
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width">
  <!-- 中略 -->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <style>/* ... */</style>
  <style>/* ... */</style>
  <style>/* ... */</style>
</head>

リロード時:

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width">
  <!-- 中略 -->
  <!-- Some Comment 1-->
  <link rel="stylesheet" href="/_astro/some-styles.css">
  <!-- Some Comment 2-->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap">
   <!-- 中略 -->
  <style>/* ... */</style>
  <style>/* ... */</style>
  <style>/* ... */</style>
</head>

Google Fontsの巻き上げによる影響

Google Fontsで埋め込みコードを取得すると次のようなコードが得られる。

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap">

このコードではスタイルシートの読み込みだけではなく、スムーズなフォントの読み込みやキャッシュの利用が出来るように事前に接続を確立するための記述が1、2行目で行われている。

しかし、ここで3行目のスタイルシートの読み込みのみが巻き上げられて最上位に来てしまうと、HTMLは基本的に先頭から解釈されていくため、1、2行目の指定が無意味になる可能性がある。

調査と原因の推測

公式で明示的に言及している箇所は見つけられなかった。

ただし、Astroのスタイリングに関するドキュメントには、スタイルシートのカスケード順序についての記述があり、<link>要素のスタイルは最も優先度が低くなるとある。これを叶えるために巻き上げている可能性が考えられる。

Astroの紹介するGoogle Fontsの利用方法 Fontsource

Astroのドキュメントでは、Fontsource経由での利用が紹介されている。

https://docs.astro.build/en/guides/fonts/#using-fontsource

import "@fontsource-variable/source-serif-4";

この方法では確かに最上位への巻き上げは行われない。なぜなら、ドキュメントのカスケード順序について記述によれば、Fontsourceを利用する上での形式であるimported styles<link>よりも優先度が高く<style>よりも低いとあるためであり、仕様通りの挙動となっている。

Fontsourceを利用する場合、Google Fontsの埋め込みコードにある事前接続相当の処理は、各フォント毎のスニペットに記載されていないため、次のドキュメントを参考にしてpreload用の記述を追加することが望ましい。

https://fontsource.org/docs/getting-started/preload

import sourceSerif4 from "@fontsource-variable/source-serif-4/files/source-serif-4-latin-wght-normal.woff2";

<link rel="preload" as="font" type="font/woff2" href={sourceSerif4} crossorigin="anonymous" />

実際の影響

少なくとも、この現象を確認したサイトでは、Fontsourceを利用したケースと比較して有意なパフォーマンス差は見受けられなかった。

そもそも、Google Fontsを直接する利用する元々の状態で、Lighthouseのパフォーマンススコアは95点以上を維持しており、巻き上げによる影響が実際にはない可能性も考えられる。

とはいえ、Google Fontsの読み込みが最上位に巻き上げられる挙動が意図したものとは思えないため、Astroにおいては紹介されているFontsourceを利用する方法が選択すると良いように思う。