投稿日: 2025年7月24日
Next.jsバージョン: 14.2 (本記事はNext.js 14の主要機能を基に構成されていますが、Next.jsは活発に開発が進められており、常に最新の情報を公式ドキュメントで確認することをお勧めします。投稿日: 2025年7月24日)
はじめに:Next.jsって何者?
従来のSPA(Single Page Application)開発には、SEO(検索エンジン最適化)への対応の難しさや、初期表示速度の遅さといった課題がありました。Next.jsはこれらの課題を解決し、よりモダンなWeb開発を可能にするために登場した、Meta社が開発した「React」をベースにしたWebアプリケーションフレームワークです。特にNext.js 13で導入されたApp Routerは、新規プロジェクトにおける推奨されるデフォルトルーティング方式であり、Next.jsの主要な特徴の多くと深く連携しています。
1. 環境構築:Next.js開発の準備
Next.jsの開発を始めるには、Node.jsとnpm(またはYarn/pnpm)が必要です。
1.1. Node.jsとnpmの確認・インストール
まず、お使いのPCにNode.jsとnpmがインストールされているか確認しましょう。ターミナル(コマンドプロンプト/PowerShell)を開き、以下のコマンドを入力します。
node -v
npm -v
推奨バージョンはNode.js v18.17以上です。もしインストールされていない場合や、バージョンが古い場合は、Node.js公式サイトからインストーラーをダウンロードするか、Homebrew(Mac)やChocolatey(Windows)などのパッケージマネージャーを使ってインストールしてください。
1.2. Next.jsプロジェクトの作成
Node.jsとnpmの準備ができたら、create-next-appという公式ツールを使ってNext.jsプロジェクトを作成します。プロジェクトを作成したいディレクトリに移動し、以下のコマンドを実行します。今回はプロジェクト名を my-nextjs-app とします。
npx create-next-app@latest my-nextjs-app
コマンドを実行すると、いくつか質問が表示されますので、以下のように回答してください。
Would you like to use TypeScript? (y/N) → y
Would you like to use ESLint? (y/N) → y
Would you like to use Tailwind CSS? (y/N) → N
Would you like to use src/ directory? (y/N) → y
Would you like to use App Router? (recommended) (y/N) → y
Would you like to use Turbopack for next dev? (y/N) → y
Would you like to customize the default import alias (@/*)? (y/N) → N
質問に答え終わると、プロジェクトの作成と必要なパッケージのインストールが始まります。
1.3. 開発サーバーの起動
インストールが完了したら、作成されたプロジェクトディレクトリに移動し、開発サーバーを起動してみましょう。
cd my-nextjs-app
npm run dev
ターミナルに以下のようなメッセージが表示されれば成功です。
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
Webブラウザを開き、http://localhost:3000 にアクセスしてみてください。Next.jsの初期画面が表示されるはずです。
1.4. プロジェクト構造の確認
VS Codeなどのエディタで、作成したmy-nextjs-appフォルダを開いてみましょう。App Routerを使用した場合の主要なディレクトリとファイルは以下のようになります。
my-nextjs-app/
├── .next/ # Next.jsのビルドキャッシュ
├── node_modules/ # インストールされたライブラリ
├── public/ # 静的ファイル(画像など)
├── src/ # ソースコードの格納ディレクトリ
│ └── app/ # App Routerのコアディレクトリ
│ ├── favicon.ico # ファビコンアイコン
│ ├── globals.css # グローバルなCSSファイル
│ ├── layout.tsx # アプリケーション全体のレイアウトを定義
│ ├── page.module.css # ページ固有のCSSモジュール
│ └── page.tsx # トップページ (ルートパス)/のコンポーネント
├── .gitigonre # Gitで管理しないファイル・ディレクトリを定義
├── eslint.config.mjs # ESLintの設定ファイル
├── next-env.d.ts # Next.jsの環境型定義ファイル
├── next.config.ts # Next.jsの設定ファイル
├── package.json # プロジェクト情報と依存関係
├── package-lock.json # パッケージのバージョン管理ファイル
├── README.md # プロジェクトの説明
└── tsconfig.json # TypeScriptの設定ファイル
- src/app/: Next.jsのApp Routerにおける中心的なディレクトリです。この中にファイルやディレクトリを作成することで、自動的にルーティングが設定されます。
- src/app/layout.tsx: アプリケーション全体に適用されるレイアウトを定義します。ヘッダーやフッターなど、全てのページで共通する要素をここに記述します。
- src/app/page.tsx: ウェブサイトのトップページ(ルートパス)に対応するコンポーネントです。
2. Next.jsの主要な特徴とApp Routerの進化
ここからは、Next.jsの強力な特徴を実際に手を動かしながら学んでいきましょう。
2.1. ファイルベースルーティング (App Router)
Next.jsのApp Routerでは、src/appディレクトリ内のファイルやディレクトリの構造に基づいて、自動的にルーティングが生成されます。これは非常に強力で直感的な機能です。
ハンズオン 2-1: 最初のコンポーネントを作成し表示する
src/app/page.tsx を開いてみてください。これはReactコンポーネントとして記述されています。既存のコードは削除またはコメントアウトして、以下のように記述してみましょう。
// src/app/page.tsx
export default function Home() {
return (
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-center">
<h1 className="text-4xl font-bold">Hello Next.js World!</h1>
<p>ここから Next.jsの旅が始まる!</p>
</main>
);
}
保存すると、開発サーバーが自動的にリロードされ、ブラウザで変更が確認できるはずです。これはNext.jsの開発サーバーがファイルの変更を検知し、即座にブラウザに反映させるホットリロードという機能によるものです。
ハンズオン 2-2: 新しいページを作成する
src/app ディレクトリの中に、aboutという新しいディレクトリを作成し、その中に page.tsx ファイルを作成します。
src/
└── app/
├── layout.tsx
├── page.tsx
└── about/ # New!
└── page.tsx # New!
src/app/about/page.tsx
の内容を以下のように記述してください。
// src/app/about/page.tsx
export default function AboutPage() {
return (
<main className="p-24">
<h1 className="text-3xl font-bold">About Us Page</h1>
<p>これは「私たちについて」のページです。</p>
</main>
);
}
ブラウザで http://localhost:3000/about にアクセスしてみてください。作成した「About Us Page」が表示されるはずです。特に設定ファイルなどを変更することなく、ファイルを作成するだけでルーティングが追加されたことに注目してください。これがNext.jsの強力なファイルベースルーティングです。
ハンズオン 2-3: ページ間の移動: Linkコンポーネント
通常のHTMLでは<a>
タグを使ってページ遷移を行いますが、Next.jsではnext/linkから提供される<Link>
コンポーネントを使うのが一般的です。
<Link>
コンポーネントの主な特徴は以下の通りです。
- クライアントサイドナビゲーション: ページ遷移時にブラウザのリロードを発生させません。
-
プリフェッチ:
<Link>
コンポーネントがビューポートに入ると、Next.jsは自動的にリンク先のページのJavaScriptバンドルをプリフェッチ(事前に読み込み)します。
src/app/page.tsx を開いて、Aboutページへのリンクを追加しましょう。
// src/app/page.tsx
import Link from 'next/link'; // Link コンポーネントをインポート
export default function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<h1 className="text-4xl font-bold">Hello Next.js World!</h1>
<p>ここから Next.jsの旅が始まる!</p>
<div className="mt-8">
{/* Linkコンポーネントの使用例 */}
<Link href="/about" className="text-blue-500 hover:underline">
About Us ページへ
</Link>
</div>
</main>
);
}
ブラウザで http://localhost:3000 にアクセスし、追加したリンクをクリックしてAboutページへ遷移できることを確認しましょう。
2.2. 豊富なデータフェッチング方法 (プリレンダリング: SSR/SSG/ISR)
Next.jsの最大の強みであり、React単体では難しい点です。Next.jsは、ユーザーにページを配信する前にHTMLを事前に生成(プリレンダリング)する機能を提供します。これにより、ユーザーがコンテンツを目にするまでの時間を短縮したり、検索エンジンがコンテンツを正しく認識しやすくする(SEO向上)といったメリットが得られます。
プリレンダリングには主に以下の方法があります。
- サーバーサイドレンダリング (SSR): ユーザーからのリクエストごとにサーバーでHTMLを生成し、それをブラウザに送ります。常に最新のデータを表示でき、SEOにも強いです。
- 静的サイト生成 (SSG): ビルド時にHTMLファイルを事前に生成しておき、CDNなどを通じて高速に配信します。更新頻度が低いコンテンツに適しています。
- Incremental Static Regeneration (ISR): SSGの高速性とSSRのデータの新しさを両立させた手法です。ビルド後に静的ページを生成しつつ、特定の時間間隔やユーザーのリクエストに基づいて、バックグラウンドで静的ページを再生成します。
ハンズオン 2-4: Server ComponentsでのデータフェッチングServer Componentsは、ビルド時またはリクエスト時にサーバーでデータを取得し、レンダリングを行います。これにより、取得したデータを含むHTMLがブラウザに配信されるため、SEOに強く、初期表示が速くなります。
src/app/page.tsx を開き、Server Componentとしてデータをフェッチしてみましょう。
// src/app/page.tsx
import Link from 'next/link';
// Server Componentとしてデータをフェッチする例
// この関数はサーバーサイドでのみ実行されます
async function getWeatherData() {
// 実際は外部APIなどからデータを取得する処理を記述します。
// ここでは学習のために、擬似的に1秒の遅延を発生させています。
await new Promise(resolve => setTimeout(resolve, 1000));
return {
location: "東京",
temperature: 28,
condition: "晴れ"
};
}
// このHome コンポーネントはServer Componentとしてレンダリングされます
// async / await を使うことで、非同期処理のデータ取得を待ってからレンダリング
export default async function Home() {
const weather = await getWeatherData(); // awaitを使ってデータを待つ
// このログは開発サーバーのターミナル (npm run devを実行しているターミナル)に出力されます
console.log("Server Componentで実行されました!");
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<h1 className="text-4xl font-bold mb-4">Hello Next.js World!</h1>
<p className="text-lg">現在地: {weather.location}</p>
<p className="text-lg">気温: {weather.temperature}°C</p>
<p className="text-lg">天気: {weather.condition}</p>
<div className="mt-8">
<Link href="/about" className="text-blue-500 hover:underline">
About Us ページへ
</Link>
</div>
</main>
);
}
ブラウザをリロードし、開発サーバーのターミナルに「Server Componentで実行されました!」と表示されることを確認してください。また、ブラウザの開発者ツールでページのソースを表示し、取得した天気情報が既にHTMLに含まれていることを確認しましょう。これがSSRの仕組みです。
ハンズオン 2-5: Client ComponentsでのデータフェッチングとインタラクションClient Componentsは、従来のReactコンポーネントと同じように、ブラウザで実行されます。useStateやuseEffectといったHooksを使って、ユーザーの操作に応じて動的にコンテンツを変更したり、データをフェッチしたりする際に利用します。
srcディレクトリの中にcomponentsというディレクトリを作成し、その中にCounter.tsxというファイルを作成します。
src/
└── app/
└── components/ # New!
└── Counter.tsx # New!
src/components/Counter.tsx
の内容を以下のように記述してください。
// src/components/Counter.tsx
'use client'; // ★これがないとServer Componentとして扱われます!
import { useState } from 'react'; // useState フックをインポート
export default function Counter() {
const [count, setCount] = useState(0);
// このログはブラウザの開発者ツールのコンソールに出力されます
console.log("Client Componentで実行されました!");
return (
<div className="flex flex-col items-center mt-8">
<h2 className="text-2xl mb-4">Counter Component</h2>
<p className="text-lg mb-4">Current Count: {count}</p>
<button
onClick={() => setCount(count + 1)}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
Increment
</button>
</div>
);
}
次に、src/app/page.tsx を開き、作成したCounterコンポーネントをインポートして使用します。
// src/app/page.tsx
import Link from 'next/link';
import Counter from '../components/Counter'; // Counter コンポーネントをインポート
async function getWeatherData() { /*... 同じコード */ }
export default async function Home() {
const weather = await getWeatherData();
console.log("Server Componentで実行されました!");
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<h1 className="text-4xl font-bold mb-4">Hello Next.js World!</h1>
<p className="text-lg">現在地: {weather.location}</p>
<p className="text-lg">気温: {weather.temperature}°C</p>
<p className="text-lg">天気: {weather.condition}</p>
<Counter /> {/* 追加! Counter コンポーネントをレンダリング */}
<div className="mt-8">
<Link href="/about" className="text-blue-500 hover:underline">
About Us ページへ
</Link>
</div>
</main>
);
}
ブラウザの開発者ツールを開き、Consoleタブを確認してください。「Client Componentで実行されました!」と表示されるはずです。Incrementボタンをクリックし、カウンターの数字が変化することを確認しましょう。
2.3. API Routes と Server Actions
Next.jsは、フロントエンドとバックエンドの連携を効率化するための機能を提供します。
- API Routes (API連携): Next.jsプロジェクト内にサーバーサイドのAPIエンドポイントを簡単に作成できる機能です。フロントエンドと同じプロジェクト内でシンプルなAPIを完結できます。
- Server Actions (Next.js 14以降の目玉機能): クライアントから直接サーバーサイドのコードを呼び出すことができる画期的な機能です。API Routesで書いていたようなサーバーサイドの処理を、よりシンプルかつ安全に実装できるようになります。
2.4. メタデータ管理によるSEO強化
Next.jsでは、ウェブページのtitleやdescriptionといったメタデータを簡単に管理できます。これはSEOにおいて非常に重要な要素です。App Routerでは、layout.tsxやpage.tsxファイル内でmetadataオブジェクトをエクスポートするだけで、動的にメタデータを設定できます。
ハンズオン 2-6: メタデータの設定と確認
src/app/layout.tsx ファイルを開き、既存のmetadataオブジェクトを以下のように変更または追加してみましょう。
// src/app/layout.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Next.js入門講座-実践的Web開発',
description: 'Next.jsの基本から最新機能までをハンズオンで学ぶ講座です。',
keywords: ['Next.js', 'React', 'Web開発', 'App Router', 'SSR', 'SSG'],
openGraph: {
title: 'Next.js入門講座',
description: 'Next.jsの基本から最新機能までをハンズオンで学ぶ講座です。',
url: 'https://your-app-url.com', // デプロイ後のURLを設定
siteName: 'Next.js入門講座',
images: [
{
url: 'https://placehold.co/1200x630/000/FFF?text=Next.js+Course', // OGP画像URL
width: 1200,
height: 630,
alt: 'Next.js入門講座のイメージ',
},
],
locale: 'ja_JP',
type: 'website',
},
twitter: {
card: 'summary_large_image',
title: 'Next.js入門講座',
description: 'Next.jsの基本から最新機能までをハンズオンで学ぶ講座です。',
creator: '@your_twitter_handle', // あなたのTwitterアカウント
images: ['https://placehold.co/1200x675/000/FFF?text=Next.js+Course+Twitter'], // Twitterカード画像URL
},
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body>{children}</body>
</html>
);
}
開発サーバーが起動していることを確認し、ブラウザで http://localhost:3000 にアクセスします。ブラウザのタブに設定したtitleが表示されていることを確認しましょう。また、ブラウザで右クリックし、「ページのソースを表示」を選択します。<head>
タグ内に、設定したdescriptionやkeywords、og:titleなどのメタデータがHTMLとして埋め込まれていることを確認してください。
2.5. エラーバウンダリとローディング状態によるUX向上
ユーザー体験を向上させるためには、データの読み込み中にローディング表示を行ったり、予期せぬエラーが発生した場合に適切なメッセージを表示したりすることが重要です。Next.jsのApp Routerでは、これらの状態を簡単に管理するための特別なファイル命名規則を提供しています。
ハンズオン 2-7: ローディングUI (loading.tsx)の実装
src/app/loading.tsx ファイルを作成し、以下のコードを記述します。
// src/app/loading.tsx
// このファイルはServer Componentとして動作します
export default function Loading() {
return (
<div className="flex justify-center items-center h-screen bg-gray-100">
<div className="animate-spin rounded-full h-10 w-10 border-t-4 border-blue-500"></div>
<p className="ml-4 text-2xl text-gray-700">データを読み込み中...</p>
</div>
);
}
次に、src/app/page.tsx のgetWeatherData関数に、意図的に長い遅延(例えば3秒)を追加して、ローディングUIが表示される時間を長くしてみましょう。
// src/app/page.tsx の getWeatherData 関数内
async function getWeatherData() {
await new Promise(resolve => setTimeout(resolve, 3000)); // 3秒の遅延
return {
location: "東京",
temperature: 28,
condition: "晴れ"
};
}
ブラウザでhttp://localhost:3000にアクセスし、データが読み込まれるまでの間、作成したローディングUIが表示されることを確認してください。
ハンズオン 2-8: エラーバウンダリ (error.tsx) の実装
src/app/error.tsx ファイルを作成し、以下のコードを記述します。
// src/app/error.tsx
"use client" // Error BoundaryはClient Componentである必要がある
import { useEffect } from "react";
export default function Error({
error, // エラーオブジェクト
// reset, // リトライするための関数
}: {
error: Error & { digest?: string }
// reset: () => void
}) {
useEffect(() => {
console.error("エラーが発生しました:", error);
}, [error]);
return (
<div className="flex flex-col items-center justify-center h-screen bg-gray-50">
<h2 className="text-3xl font-bold mb-4 text-red-600">問題が発生しました!</h2>
<p className="text-lg mb-6 text-gray-700">エラーメッセージ: {error.message}</p>
<p className="mt-4 text-sm text-gray-500">
このエラーが続く場合は、管理者にお問い合わせください。
</p>
</div>
);
}
次に、src/app/page.tsx のgetWeatherData関数に、意図的にエラーを発生させるコードを追加してみましょう(例えば、一定の確率でエラーを投げる)。
// src/app/page.tsx の getWeatherData 関数内
async function getWeatherData() {
await new Promise(resolve => setTimeout(resolve, 3000));
// ★デモ用に意図的にエラーを発生させるコードを追加
if (Math.random() < 0.5) { // 50%の確率でエラーを発生
throw new Error("天気情報の取得に失敗しました。");
}
return {
location: "東京",
temperature: 28,
condition: "晴れ"
};
}
ブラウザでhttp://localhost:3000にアクセスし、ページを何度かリロードしてみてください。エラーが発生した場合に、作成したエラーバウンダリUIが表示されることを確認しましょう。
まとめ
本記事では、Next.jsの環境構築から、App Routerにおけるファイルベースルーティング、Server ComponentsとClient Componentsの使い分けによるデータフェッチング、メタデータ管理、そしてローディングUIとエラーバウンダリの実装までをハンズオン形式で学びました。
Next.jsは、SEOやパフォーマンスが重要なWebサイトから、動的なWebアプリケーションまで、幅広いプロジェクトで非常に強力な選択肢となります。本記事が、皆さんのNext.js開発の第一歩となることを願っています。