©️

next/fontはCIでモック推奨

2023/11/29に公開

Next.jsではnext/fontを活用することで、Googleフォントをセルフホスティングすることができ、Googleへの通信が発生しないことにより、ページの読み込み速度を向上することができます。
next/fontの使い方などは公式ドキュメント等に委ねますが、next/fontかつCIを導入している方にモック化することを勧めたく思います。

なぜモック化するのか

run buildなど実行時にフォント取得に失敗する場合があります。
どういったCIを組んでいるかにもよりますが、それが原因でCI自体が失敗する可能性があります。
頻度としては10回に1回もない程度で、再実行すれば解消しますが、ストレスを減らすためにmock化するのが好ましいです。

storybookのdocにでもモックを推奨されてます。
https://github.com/storybookjs/storybook/blob/next/code/frameworks/nextjs/README.md#mocking-fonts-during-testing

どうモックかするか

上記のstorybookのドキュメントで確認できますが、やることとしては大きく2つで、
CI側に環境変数を設定するのと、モックを作成することです。

環境変数の設定

run buildなどフォント取得リクエストが実行されるステップにNEXT_FONT_GOOGLE_MOCKED_RESPONSESを設定します。

        env:
          NEXT_FONT_GOOGLE_MOCKED_RESPONSES: ${{ github.workspace }}/mocked-google-fonts.js
        run: npm run build --ignore-scripts

NEXT_FONT_GOOGLE_MOCKED_RESPONSESを設定すると、Googleへのリクエストは実行せず、指定したJavaScriptのモックを参照するようになります。

モックの作成

モックは以下のように設定します。

module.exports = {
  'https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;600;700&display=swap': `
    @font-face {
        font-family: 'Noto Sans JP';
        font-style: normal;
        font-weight: 400;
        font-display: swap;
        src: url(https://fonts.gstatic.com/s/notosansjp/v52/-F62fjtqLzI2JPCgQBnw7HFowwII2lcnk-AFfrgQrvWXpdFg3KXxAMsKMbdN.0.woff2) format('woff2');
        unicode-range: U+25ee8, U+25f23, ・・・・・・;
    }
`,
  'https://fonts.googleapis.com/css2?family=Roboto:wght@700&display=swap': `
    @font-face {
        font-family: 'Roboto';
        font-style: normal;
        font-weight: 700;
        font-display: swap;
        src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCRc4AMP6lbBP.woff2) format('woff2');
        unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
    }
`,
}

リクエストのURLと@font-faceを指定します。
リクエストはプロダクションコードで読み込んでいるものと一致させます。
今回の例だとLayoutで以下のように読み込んでいます。

const notoSansJP = Noto_Sans_JP({
  weight: ['400', '500', '600', '700'],
  display: 'swap',
  preload: false,
})

const roboto = Roboto({
  weight: ['700'],
  display: 'swap',
  preload: false,
  variable: '--font-roboto',
})

これと合わせる形でURLを指定する必要があります。
URLは公式サイトから確認できます。
https://fonts.google.com/
参照方法は以下が参考になります。
https://big-mac.jp/column/lets-try-using-web-font-setting-guide-google-fonts/

@font-faceは厳密に設定する必要はないですが、私は実際にAPIを叩いて取得された先頭のものを設定しています。

まとめ

next/fontを導入していて、CIでもフォント取得が走る場合は稀にエラーになるので、モック化することをお勧めします。

Discussion