TechBlog

Next.js入門|App Routerの基本・SSR/SSGの違い・最初のアプリを作る手順

by あくえり
#Next.js #React #SSR #Web開発 #初心者
Next.js入門ガイド
目次

Next.jsとは何か

Next.jsは、ReactをベースにしたWebアプリケーションフレームワークです。Vercelが開発・メンテナンスしており、2024年時点でReactエコシステムにおける最も普及したフレームワークのひとつです。

ReactだけとNext.jsの違い:

Reactは「UIを作るためのライブラリ」であり、ルーティングやサーバーサイドレンダリングなどの機能は自分で設定する必要があります。一方Next.jsはこれらの機能がすべてビルトインで提供されます。

機能React単体Next.js
ルーティングreact-routerなど別途必要ファイルベースで自動設定
SSR/SSG追加設定が必要標準対応
画像最適化手動対応<Image>コンポーネントで自動
フォント最適化手動対応next/fontで自動
API Routes別サーバーが必要同一プロジェクト内に作成可能

プロジェクトの作成

create-next-app を使うと、設定が整った状態でプロジェクトを作成できます。

npx create-next-app@latest my-app

コマンドを実行すると、いくつかの質問が表示されます。初心者には以下の設定がおすすめです。

Would you like to use TypeScript? › Yes
Would you like to use ESLint? › Yes
Would you like to use Tailwind CSS? › Yes
Would you like your code inside a `src/` directory? › Yes
Would you like to use App Router? › Yes
Would you like to use Turbopack for next dev? › Yes
Would you like to customize the import alias? › No

作成後、開発サーバーを起動します。

cd my-app
npm run dev

http://localhost:3000 にアクセスすると、Next.jsのデフォルトページが表示されます。


App Routerのディレクトリ構造

Next.js 13で導入されたApp Routerでは、src/app/ ディレクトリ内のファイル配置がそのままURLになります。

src/
└── app/
    ├── layout.tsx        # ルートレイアウト(全ページ共通)
    ├── page.tsx          # / (トップページ)
    ├── loading.tsx       # ローディング画面
    ├── not-found.tsx     # 404ページ
    ├── globals.css       # グローバルCSS
    ├── about/
    │   └── page.tsx      # /about ページ
    ├── blog/
    │   ├── page.tsx      # /blog ページ(記事一覧)
    │   └── [slug]/
    │       └── page.tsx  # /blog/記事のスラッグ(動的ルート)
    └── api/
        └── posts/
            └── route.ts  # /api/posts(APIエンドポイント)

layout.tsx(ルートレイアウト)

全ページに共通するHTMLの骨格を定義します。ヘッダー・フッターなどを配置する場所です。

// src/app/layout.tsx
import type { Metadata } from 'next';
import { Noto_Sans_JP } from 'next/font/google';
import './globals.css';

const notoSansJP = Noto_Sans_JP({
  subsets: ['latin'],
  weight: ['400', '700'],
});

export const metadata: Metadata = {
  title: 'My Blog',
  description: 'Next.jsで作ったブログです',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ja">
      <body className={notoSansJP.className}>
        <header className="border-b px-4 py-3">
          <a href="/" className="text-xl font-bold">My Blog</a>
        </header>
        <main className="max-w-3xl mx-auto px-4 py-8">
          {children}
        </main>
        <footer className="border-t px-4 py-6 text-center text-sm text-gray-500">
          © 2026 My Blog
        </footer>
      </body>
    </html>
  );
}

page.tsx(ページコンポーネント)

// src/app/page.tsx
export default function HomePage() {
  return (
    <div>
      <h1 className="text-3xl font-bold mb-4">ようこそ</h1>
      <p className="text-gray-600">Next.jsで作ったブログです。</p>
    </div>
  );
}

ファイルベースルーティング

App Routerでは、app/ 以下のフォルダ名がURLパスになります。

ファイルパスURL
app/page.tsx/
app/about/page.tsx/about
app/blog/page.tsx/blog
app/blog/[slug]/page.tsx/blog/任意の値
app/shop/[...slug]/page.tsx/shop/a/b/c など

[slug] のような角括弧で囲まれたフォルダは「動的ルート」と呼ばれ、URLのパラメータとして値を受け取れます。

// src/app/blog/[slug]/page.tsx
type Props = {
  params: { slug: string };
};

export default function BlogPost({ params }: Props) {
  return (
    <article>
      <h1>記事スラッグ: {params.slug}</h1>
    </article>
  );
}

Server ComponentsとClient Componentsの違い

App RouterではデフォルトですべてのコンポーネントがServer Components(サーバーコンポーネント)として動作します。

Server Components(デフォルト):

  • サーバー側でHTMLとして生成される
  • データベースや外部APIへのアクセスをコンポーネント内で直接行える
  • useStateuseEffect などのReact Hooksは使えない
  • JavaScriptがクライアントに送られないのでバンドルサイズが増えない

Client Components:

  • ファイルの先頭に 'use client' と記述する
  • ブラウザ上で動作し、React Hooksが使える
  • インタラクティブなUI(クリックイベント、フォーム状態管理など)に使う
// Server Component(データ取得)
// src/app/blog/page.tsx
async function getPosts() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5');
  return res.json();
}

export default async function BlogPage() {
  const posts = await getPosts();

  return (
    <div>
      <h1 className="text-2xl font-bold mb-6">記事一覧</h1>
      <ul className="space-y-4">
        {posts.map((post: { id: number; title: string }) => (
          <li key={post.id} className="border rounded-lg p-4">
            <a href={`/blog/${post.id}`} className="font-medium hover:text-blue-600">
              {post.title}
            </a>
          </li>
        ))}
      </ul>
    </div>
  );
}
// Client Component(インタラクティブなUI)
// src/components/LikeButton.tsx
'use client';

import { useState } from 'react';

export default function LikeButton() {
  const [count, setCount] = useState(0);

  return (
    <button
      onClick={() => setCount(count + 1)}
      className="px-4 py-2 bg-red-50 text-red-600 rounded-full hover:bg-red-100"
    >
      ♥ {count}
    </button>
  );
}

SSR・SSG・ISRの使い分け

SSR(Server-Side Rendering)

リクエストのたびにサーバーでHTMLを生成します。リアルタイム性が必要なデータに向いています。

// Next.js App Routerでは、fetchのcacheオプションで制御
export default async function Page() {
  // cache: 'no-store' でSSR(毎回サーバーで生成)
  const data = await fetch('https://api.example.com/data', {
    cache: 'no-store',
  });
  const json = await data.json();

  return <div>{json.title}</div>;
}

SSG(Static Site Generation)

ビルド時にHTMLを一度生成して静的ファイルとして配信します。ブログ・ドキュメントサイトに最適です。

// cache: 'force-cache'(デフォルト)でSSG
export default async function Page() {
  const data = await fetch('https://api.example.com/data', {
    cache: 'force-cache',
  });
  const json = await data.json();

  return <div>{json.title}</div>;
}

ISR(Incremental Static Regeneration)

SSGで生成した静的ファイルを一定時間ごとに再生成します。ブログや商品ページなど、データが時々更新されるコンテンツに向いています。

// next.revalidate でISR(指定秒数後に再生成)
export default async function Page() {
  const data = await fetch('https://api.example.com/data', {
    next: { revalidate: 3600 }, // 1時間ごとに再生成
  });
  const json = await data.json();

  return <div>{json.title}</div>;
}

Link・Image・Fontコンポーネント

Next.jsには、パフォーマンスを自動的に最適化するコンポーネントが用意されています。

import Link from 'next/link';
import Image from 'next/image';
import { Inter } from 'next/font/google';

const inter = Inter({ subsets: ['latin'] });

export default function Example() {
  return (
    <div className={inter.className}>
      {/* Linkコンポーネント:クライアントサイドナビゲーション */}
      <Link href="/about" className="text-blue-500 hover:underline">
        Aboutページへ
      </Link>

      {/* Imageコンポーネント:自動的にWebP変換・遅延読み込み・サイズ最適化 */}
      <Image
        src="/images/sample.jpg"
        alt="サンプル画像"
        width={800}
        height={400}
        priority  // ファーストビューの画像にはpriority属性を付ける
      />
    </div>
  );
}

実践:シンプルなブログ風ページの作成

以下は、JSONPlaceholderのAPIを使って記事一覧と詳細ページを作る最小構成の例です。

// src/app/blog/page.tsx(記事一覧)
type Post = {
  id: number;
  title: string;
  body: string;
};

export default async function BlogListPage() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=10', {
    next: { revalidate: 3600 },
  });
  const posts: Post[] = await res.json();

  return (
    <div>
      <h1 className="text-3xl font-bold mb-8">ブログ一覧</h1>
      <div className="space-y-4">
        {posts.map((post) => (
          <Link
            key={post.id}
            href={`/blog/${post.id}`}
            className="block border rounded-lg p-4 hover:border-blue-300 hover:bg-blue-50 transition-colors"
          >
            <h2 className="font-semibold text-gray-900">{post.title}</h2>
            <p className="text-sm text-gray-500 mt-1 line-clamp-2">{post.body}</p>
          </Link>
        ))}
      </div>
    </div>
  );
}
// src/app/blog/[id]/page.tsx(記事詳細)
type Props = {
  params: { id: string };
};

export default async function BlogDetailPage({ params }: Props) {
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`, {
    next: { revalidate: 3600 },
  });
  const post = await res.json();

  return (
    <article>
      <h1 className="text-3xl font-bold mb-4">{post.title}</h1>
      <p className="text-gray-700 leading-relaxed">{post.body}</p>
      <div className="mt-8">
        <Link href="/blog" className="text-blue-500 hover:underline">
記事一覧に戻る
        </Link>
      </div>
    </article>
  );
}

Next.js超入門

Next.jsの基礎からApp Router、サーバーコンポーネント、データフェッチまでを丁寧に解説した日本語入門書。これからNext.jsを始める方に最適な一冊です。

※ アフィリエイトリンクを含みます

Udemy — Next.js 14 & React - The Complete Guide

Next.js 14のApp Router、Server Actions、認証実装まで網羅した英語ベストセラー講座。ハンズオン形式で実践的なアプリ開発スキルが身につきます。

¥1,500〜 Udemyで見る

※ アフィリエイトリンクを含みます


まとめ

Next.jsはファイルベースのルーティング、Server/Client Componentsの使い分け、SSR/SSG/ISRのデータフェッチ戦略など、現代のWeb開発に必要な機能が揃ったフレームワークです。create-next-app でプロジェクトを作成し、app/page.tsx を編集するところから始めましょう。Server Componentsでデータを取得してHTMLを組み立て、インタラクティブな部分にだけ 'use client' を使うというパターンを身につけることが、Next.js習得の第一歩です。

共有: