フォントと画像の最適化

前の章では、Next.jsアプリケーションのスタイリング方法を学びました。カスタムフォントとヒーロー画像を追加して、ホームページの作業を続けましょう。

フォントを最適化する理由

フォントはウェブサイトのデザインにおいて重要な役割を果たしますが、プロジェクトでカスタムフォントを使用すると、フォントファイルの取得と読み込みが必要な場合、パフォーマンスに影響を与える可能性があります。

Cumulative Layout Shift(累積レイアウトシフト)は、Googleがウェブサイトのパフォーマンスとユーザーエクスペリエンスを評価するために使用する指標です。フォントに関して、レイアウトシフトは、ブラウザが最初にフォールバックまたはシステムフォントでテキストをレンダリングし、カスタムフォントが読み込まれた後にそれを置き換えるときに発生します。この置き換えにより、テキストのサイズ、間隔、またはレイアウトが変更され、周囲の要素が移動する可能性があります。

カスタムフォントが読み込まれる際のレイアウトシフトを示すページの初期読み込みを模したUI

Next.jsでは、next/fontモジュールを使用すると、アプリケーション内のフォントが自動的に最適化されます。ビルド時にフォントファイルをダウンロードし、他の静的アセットと共にホストします。これにより、ユーザーがアプリケーションを訪問した際に、パフォーマンスに影響を与える追加のネットワークリクエストが発生しません。

プライマリフォントの追加

アプリケーションにカスタムGoogleフォントを追加して、この仕組みを確認してみましょう。

/app/uiフォルダ内に、fonts.tsという新しいファイルを作成します。このファイルを使用して、アプリケーション全体で使用するフォントを管理します。

next/font/googleモジュールからInterフォントをインポートします - これがプライマリフォントになります。次に、読み込むサブセットを指定します。ここでは'latin'を使用します:

/app/ui/fonts.ts
import { Inter } from 'next/font/google';
 
export const inter = Inter({ subsets: ['latin'] });

最後に、/app/layout.tsx<body>要素にフォントを追加します:

/app/layout.tsx
import '@/app/ui/global.css';
import { inter } from '@/app/ui/fonts';
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={`${inter.className} antialiased`}>{children}</body>
    </html>
  );
}

Inter<body>要素に追加することで、フォントがアプリケーション全体に適用されます。ここでは、フォントを滑らかにするTailwindのantialiasedクラスも追加しています。このクラスを使用する必要はありませんが、見栄えが良くなります。

ブラウザで開発者ツールを開き、body要素を選択してください。スタイルの下にInterInter_Fallbackが適用されているのが確認できるはずです。

練習: セカンダリフォントの追加

アプリケーションの特定の要素にフォントを追加することもできます。

次はあなたの番です!fonts.tsファイルにLusitanaというセカンダリフォントをインポートし、/app/page.tsxファイルの<p>要素に渡してください。前に指定したサブセットに加えて、異なるフォントウェイト(例:400(通常)と700(太字))も指定してください。

準備ができたら、以下のコードスニペットを展開して解決策を確認してください。

ヒント:

  • フォントに渡すウェイトオプションがわからない場合は、コードエディタのTypeScriptエラーを確認してください。
  • Google Fontsウェブサイトにアクセスし、Lusitanaを検索して利用可能なオプションを確認してください。
  • 複数のフォントの追加全オプションのリストのドキュメントを参照してください。

最後に、<AcmeLogo />コンポーネントもLusitanaを使用しています。エラーを防ぐためにコメントアウトされていましたが、今ならコメントを解除できます:

/app/page.tsx
// ...
 
export default function Page() {
  return (
    <main className="flex min-h-screen flex-col p-6">
      <div className="flex h-20 shrink-0 items-end rounded-lg bg-blue-500 p-4 md:h-52">
        <AcmeLogo />
        {/* ... */}
      </div>
    </main>
  );
}

素晴らしい、アプリケーションに2つのカスタムフォントを追加しました!次に、ホームページにヒーロー画像を追加しましょう。

画像を最適化する理由

Next.jsは、トップレベルの/publicフォルダの下に画像などの静的アセットを提供できます。/public内のファイルはアプリケーションで参照できます。

通常のHTMLでは、次のように画像を追加します:

<img
  src="/hero.png"
  alt="ダッシュボードプロジェクトのデスクトップ版を示すスクリーンショット"
/>

しかし、これには手動で以下の対応が必要です:

  • 異なる画面サイズで画像がレスポンシブであることを確認する。
  • 異なるデバイス向けに画像サイズを指定する。
  • 画像の読み込み時にレイアウトシフトを防ぐ。
  • ユーザーのビューポート外にある画像を遅延読み込みする。

画像最適化はウェブ開発における大きなトピックであり、それ自体が専門領域と言えるでしょう。これらの最適化を手動で実装する代わりに、next/imageコンポーネントを使用して画像を自動的に最適化できます。

<Image>コンポーネント

<Image>コンポーネントはHTMLの<img>タグを拡張したもので、以下のような自動画像最適化機能を備えています:

  • 画像の読み込み時に自動的にレイアウトシフトを防止。
  • ビューポートが小さいデバイスに大きな画像を送信しないようリサイズ。
  • デフォルトで遅延読み込み(ビューポートに入った時点で画像を読み込み)。
  • ブラウザがサポートしている場合、WebPAVIFなどの最新フォーマットで画像を提供。

デスクトップヒーロー画像の追加

<Image>コンポーネントを使用してみましょう。/publicフォルダ内を見ると、hero-desktop.pnghero-mobile.pngの2つの画像があります。これらは完全に異なる画像で、ユーザーのデバイスがデスクトップかモバイルかに応じて表示されます。

/app/page.tsxファイルで、next/imageからコンポーネントをインポートします。次に、コメントの下に画像を追加します:

/app/page.tsx
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
import Link from 'next/link';
import { lusitana } from '@/app/ui/fonts';
import Image from 'next/image';
 
export default function Page() {
  return (
    // ...
    <div className="flex items-center justify-center p-6 md:w-3/5 md:px-28 md:py-12">
      {/* ヒーロー画像をここに追加 */}
      <Image
        src="/hero-desktop.png"
        width={1000}
        height={760}
        className="hidden md:block"
        alt="ダッシュボードプロジェクトのデスクトップ版を示すスクリーンショット"
      />
    </div>
    //...
  );
}

ここでは、width1000height760ピクセルに設定しています。レイアウトシフトを防ぐために画像のwidthheightを設定するのは良い習慣です。これらは画像がレンダリングされるサイズではなく、アスペクト比を理解するための実際の画像ファイルのサイズです。

また、モバイル画面では画像をDOMから削除するhiddenクラスと、デスクトップ画面で画像を表示するmd:blockクラスにも注目してください。

これが現在のホームページの見た目です:

カスタムフォントとヒーロー画像が適用されたスタイル済みホームページ

練習: モバイルヒーロー画像の追加

次はあなたの番です!先ほど追加した画像の下に、hero-mobile.png用の別の<Image>コンポーネントを追加してください。

  • 画像のwidth560height620ピクセルに設定します。
  • モバイル画面で表示され、デスクトップでは非表示にする必要があります - 開発者ツールを使用して、デスクトップとモバイルの画像が正しく切り替わっているか確認できます。

準備ができたら、以下のコードスニペットを展開して解決策を確認してください。

素晴らしい!ホームページにカスタムフォントとヒーロー画像が追加されました。

推奨読書

これらのトピックには、リモート画像の最適化やローカルフォントファイルの使用など、さらに学ぶべきことがたくさんあります。フォントと画像についてさらに深く学びたい場合は、以下を参照してください:

On this page