Next.jsでフォントと画像を最適化する方法
※本記事は、Next.jsのチュートリアル備忘録です
https://nextjs.org/learn/dashboard-app/optimizing-fonts-images
この記事で学べること
- Next.jsでカスタムフォントを追加する方法(next/fontの使い方)
- Next.jsで画像を最適化して表示する方法(next/imageの使い方)
- なぜフォントと画像の最適化が重要なのか
フォントの最適化とは何か?
フォントが重要な理由
Webサイトにおいて、フォント(文字の種類・デザイン)は見た目の印象を大きく左右します。しかし、カスタムフォント(独自の文字デザイン)を使うと、パフォーマンス(サイトの表示速度)に悪影響を与えることがあります。
レイアウトシフトという問題
レイアウトシフトとは、ページを読み込んだ時に文字や要素の位置がずれる現象です。
具体的な流れ:
- 最初にブラウザが標準フォントでテキストを表示
- カスタムフォントが読み込まれると、文字が入れ替わる
- この時、文字のサイズや間隔が変わって、他の要素の位置もずれる
これはユーザーにとって非常に不快な体験となります。
Next.jsのフォント最適化機能:処理の全体像
Next.jsはnext/font
モジュールを使って、この問題を自動的に解決します:
開発時 → ビルド時 → 本番配信 → ユーザーアクセス
1. 開発時
- あなたがコードを書いている段階
-
next/font/google
でフォントを指定しただけの状態
2. ビルド時(npm run build
実行時)
- Next.jsがあなたのコードを解析
- 「Interフォントが必要だな」と判断
- GoogleフォントのサーバーからInterフォントファイルをダウンロード
- ダウンロードしたフォントファイルを、あなたのサイトの一部として保存
3. 本番配信
- ビルドで作られたファイル(フォント含む)をサーバーにアップロード
- フォントファイルは、あなたのサイトのファイルとして存在
4. ユーザーアクセス時
- ユーザーがサイトを訪問
- フォントは既にあなたのサイトの一部なので、追加でGoogleに取りに行く必要がない
- 高速表示が可能
従来の方法との比較
従来の方法(遅い):
ユーザー訪問 → HTMLを取得 → CSSを解析 → 「Googleフォントが必要」と判明 → Googleサーバーにフォント取得 → 表示
Next.jsの方法(速い):
ユーザー訪問 → HTMLとフォントを同時に取得 → すぐに表示
実際のフォント設定方法
1. プライマリフォント(基本フォント)の設定
まず、アプリケーション全体で使用するメインフォントを設定します。
手順1: フォントファイルを作成
/app/ui/fonts.ts
というファイルを作成し、以下のコードを記述:
import { Inter } from 'next/font/google';
export const inter = Inter({ subsets: ['latin'] });
解説:
-
Inter
:Googleフォントの一つで、読みやすいモダンなフォント -
subsets: ['latin']
:ラテン文字(英語など)のみを読み込む設定 -
export
:他のファイルからこのフォントを使えるようにする
手順2: レイアウトファイルに適用
/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.className
:Next.jsが自動生成するユニークなCSSクラス名を取得(例:"__Inter_abc123"
のようなランダムな文字列) -
antialiased
:文字を滑らかに表示するTailwind CSSのクラス -
<body>
要素に適用することで、アプリケーション全体にフォントが適用される
CSSクラス名の自動生成について
console.log(inter.className);
// 結果: "__Inter_abc123" のようなランダムな文字列
Next.jsが自動で以下のようなCSSを生成:
.__Inter_abc123 {
font-family: 'Inter', sans-serif;
/* その他のフォント設定 */
}
このユニークなクラス名により:
- フォントの設定が他のCSSと競合しない
- 確実にInterフォントが適用される
- CSS管理が自動化される
2. セカンダリフォント(部分的なフォント)の設定
特定の要素にだけ使用するフォントも設定できます。
fonts.tsファイルに追加:
import { Inter, Lusitana } from 'next/font/google';
export const inter = Inter({ subsets: ['latin'] });
export const lusitana = Lusitana({
subsets: ['latin'],
weight: ['400', '700'], // 通常の太さと太字を指定
});
解説:
-
Lusitana
:セリフ系の装飾的なフォント -
weight: ['400', '700']
:400は通常の太さ、700は太字を指定
フォントの太さ(weight)の使い分け
// 通常の太さで表示
<p className={`${lusitana.className} font-normal`}>
これは通常の太さです(weight: 400を使用)
</p>
// 太字で表示
<p className={`${lusitana.className} font-bold`}>
これは太字です(weight: 700を使用)
</p>
TailwindCSSのfontクラス:
-
font-normal
:weight 400を使用 -
font-bold
:weight 700を使用 -
font-light
:weight 300を使用(事前に指定が必要)
数値での直接指定も可能:
<p className={`${lusitana.className}`} style={{fontWeight: 400}}>
通常の太さ
</p>
<p className={`${lusitana.className}`} style={{fontWeight: 700}}>
太字
</p>
画像の最適化とは何か?
通常のHTMLでの画像表示の問題点
一般的なHTMLでは、画像を以下のように表示します:
<img
src="/hero.png"
alt="ダッシュボードのデスクトップ版スクリーンショット"
/>
しかし、この方法では以下の問題があります:
- レスポンシブ対応:異なる画面サイズに対応できない
- 画像サイズの最適化:デバイスに応じた適切なサイズ指定が必要
- レイアウトシフト:画像読み込み時の要素位置のずれ
- 遅延読み込み:画面外の画像も最初から読み込んでしまう
Next.jsの画像最適化機能
Next.jsの<Image>
コンポーネントは、これらの問題を自動的に解決します:
- 自動レイアウトシフト防止:画像読み込み時の位置ずれを防ぐ
- 自動リサイズ:デバイスに応じた適切なサイズで配信
- 遅延読み込み:画面に表示される直前に画像を読み込む
- モダンフォーマット対応:WebPやAVIF形式での配信(対応ブラウザのみ)
画像フォーマットについて
WebP(ウェッピー):
- 読み方:「ウェッピー」
- 開発元:Google
- 特徴:JPEGやPNGより30-35%小さいファイルサイズ
- 対応ブラウザ:現代のほぼ全てのブラウザ
AVIF(エーブイアイエフ):
- 読み方:「エーブイアイエフ」
- 開発元:Alliance for Open Media
- 特徴:WebPよりもさらに50%小さいファイルサイズ
- 対応ブラウザ:比較的新しいブラウザのみ
Next.jsの自動変換:
<Image src="/photo.jpg" width={500} height={300} alt="写真" />
Next.jsが自動で判断:
- 最新ブラウザ → AVIF形式で配信(最小サイズ)
- 少し古いブラウザ → WebP形式で配信(中間サイズ)
- 古いブラウザ → 元のJPG形式で配信(互換性重視)
実際の画像設定方法
1. デスクトップ用画像の設定
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>
);
}
解説:
-
src="/hero-desktop.png"
:publicフォルダ内の画像ファイルを指定 -
width={1000} height={760}
:画像の実際のサイズを指定(アスペクト比を維持) -
className="hidden md:block"
:モバイルでは非表示、デスクトップでは表示 -
alt
:画像の説明文(アクセシビリティのため必須)
width・heightとアスペクト比について
{ }
は「JavaScriptの値を埋め込む」という意味で、文字列ではなく数値として渡しています。
// 元画像: 1000x760 (比率 1.32:1)
<Image
src="/image.jpg"
width={1000}
height={760}
className="w-full" // 実際の表示は画面幅に合わせる
/>
仕組み:
-
width={1000} height={760}
で元画像の比率をNext.jsに教える -
className="w-full"
で実際の表示サイズを指定 - Next.jsが比率を維持しながら、適切なサイズで表示
具体例:
元画像: 1000x760
画面幅: 500px
→ 自動計算: 500x380で表示(比率維持)
2. モバイル用画像の設定とレスポンシブ表示
<Image
src="/hero-mobile.png"
width={560}
height={620}
className="block md:hidden"
alt="ダッシュボードのモバイル版スクリーンショット"
/>
レスポンシブクラスの詳細解説
block
の意味:
block
は「表示する」という意味です。
className="block" // display: block; (表示)
className="hidden" // display: none; (非表示)
className="inline" // display: inline; (インライン表示)
className="flex" // display: flex; (フレックス表示)
block md:hidden
の詳細:
className="block md:hidden"
これを分解すると:
-
block
:デフォルト(全サイズ)で表示 = モバイル(0px以上)で表示 -
md:hidden
:md(768px以上)で非表示 = タブレット・デスクトップで非表示
結果:
-
0〜767px(モバイル):
block
が適用 → 表示 -
768px以上(タブレット・PC):
md:hidden
が適用 → 非表示
TailwindCSSのブレークポイント
TailwindCSSのサイズ区分:
-
sm
: 640px以上(小さなタブレット) -
md
: 768px以上(タブレット) -
lg
: 1024px以上(デスクトップ) -
xl
: 1280px以上(大きなデスクトップ)
様々な表示パターン
// デスクトップのみ表示
className="hidden md:block"
// 0〜767px(モバイル):非表示、768px以上(PC):表示
// モバイルのみ表示
className="block md:hidden"
// 0〜767px(モバイル):表示、768px以上(PC):非表示
// スマホ・タブレットのみ表示
className="block lg:hidden"
// 0〜1023px:表示、1024px以上:非表示
// デスクトップのみ表示
className="hidden lg:block"
// 0〜1023px:非表示、1024px以上:表示
// 複雑な組み合わせ(スマホ: 非表示、タブレット: 表示、デスクトップ: 非表示)
className="hidden md:block lg:hidden"
実用的なコード例
// モバイル用画像(モバイルでのみ表示)
<Image
src="/hero-mobile.png"
width={560}
height={620}
className="block md:hidden" // スマホ:表示、PC:非表示
alt="モバイル版"
/>
// デスクトップ用画像(デスクトップでのみ表示)
<Image
src="/hero-desktop.png"
width={1000}
height={760}
className="hidden md:block" // スマホ:非表示、PC:表示
alt="デスクトップ版"
/>
重要なポイント
フォントについて
- パフォーマンス:next/fontを使うことで、フォント読み込みによる速度低下を防げる
- ユーザー体験:レイアウトシフトを防ぐことで、快適な閲覧体験を提供
- 管理の容易さ:一箇所でフォントを管理することで、メンテナンスが簡単
- 自動最適化:ビルド時にフォントを取得し、静的アセットとして配信することで高速化
画像について
- 自動最適化:手動で行うべき最適化を自動化
- パフォーマンス向上:適切なサイズと形式で画像を配信
- SEO対策:適切なalt属性により検索エンジン最適化にも寄与
- レスポンシブ対応:デバイスに応じた画像の出し分けが簡単
レスポンシブデザインについて
- TailwindCSSとの組み合わせ:直感的なクラス名でレスポンシブ対応が可能
- モバイルファースト:小さい画面から設計し、大きい画面向けに拡張
- 適切な画像の使い分け:デバイスに最適化された画像で表示速度向上
まとめ
Next.jsのフォントと画像の最適化機能を使うことで:
- 開発効率が向上:複雑な最適化処理を自動化
- ユーザー体験が改善:高速で快適なWebサイトを実現
- メンテナンスが容易:統一された管理方法
- レスポンシブ対応が簡単:TailwindCSSとの組み合わせで直感的な実装
これらの機能を活用することで、プロフェッショナルなWebアプリケーションを効率的に構築できます。特に、ビルド時の最適化やレスポンシブ表示の仕組みを理解することで、より効果的にNext.jsを活用できるようになります。