はじめに
React を触り始めたとき、「コンポーネントは書けるけど、アプリ全体としてどう組み立てればいいの?」という壁に当たりがちです。ルーティング、API 通信、SEO、ビルド、デプロイ——“画面が出る”だけでは済まない要素が一気に増えます。
Next.js は、その「アプリに必要な周辺機能」を最初から揃えたフレームワークです。React の開発体験を保ちつつ、ルーティングや最適化、サーバー側の処理まで自然につなげられるのが強みです。
ただし、最初の学習でつまずくポイントもあります。たとえば 「App Router と Pages Router の違い」、「Server Component / Client Component」、「データ取得はどこでやるのが正解?」 など、概念が多いからです。
この記事では、Next.js を「なんとなく使える」ではなく、なぜそう書くのかが腹落ちする入門を目指します。座学で地図を作ってから、ハンズオンで小さなアプリを完成させます。
座学
1) Next.js は何を解決するのか
Next.js の価値は、ざっくり言うとこの3つです。
- ルーティングが仕組みとして組み込まれている(URL と画面が自然につながる)
- 表示の最適化(SSR/SSG/ISR)が選べる(SEO・速度・更新頻度のバランスを取れる)
- サーバー処理(API / Server Actions / ミドルウェア)が同居できる(フロントとバックを“近く”に置ける)
React 単体だと、ルータやビルド、データ取得の設計を自分で寄せ集めます。Next.js はそれらを「よくある形」で統合してくれるので、設計の迷子になりにくいです。
2) App Router の基本:app/ が入口
最近の Next.js は **App Router(app/ ディレクトリ)**が中心です。入門でもこちらから始めるのが今の主流です。
app/page.tsx…/(トップ)app/about/page.tsx…/aboutapp/blog/[slug]/page.tsx…/blog/xxx(動的ルート)
「フォルダ = ルート」、page.tsx = そのページ、この規則が軸になります。
3) Server Component と Client Component(重要)
App Router では、コンポーネントが大きく2種類に分かれます。
- Server Component(デフォルト)
- サーバー側でレンダリングされる
- DB 取得や秘密情報を扱いやすい
- ただし
useStateやonClickなどのブラウザ機能は使えない
- Client Component(先頭に
'use client')- ブラウザ側で動く
- クリック・状態管理・DOM 操作ができる
- ただしバンドルが増えるので増やしすぎ注意
入門でのコツはシンプルで、
**「表示だけは Server、操作が必要な部品だけ Client」**にするのが基本です。
4) データ取得の考え方:どこで fetch する?
Next.js では「どこでデータを取るか」が設計の要になります。
- Server Component で fetch
- 速い / SEO に強い / 秘密を隠せる
- 画面表示に必要なデータはまずここで検討
- Client Component で fetch
- ユーザー操作に応じて再取得したいとき(検索、フィルタなど)
- 体験は良いが、初期表示の SEO とは相性が変わる
まずは 「ページ表示に必要なもの=Serverで」、
「操作で変わるもの=Clientで」 と覚えると迷いにくいです。
ハンズオン
ここでは、**「記事一覧 → 詳細 → お気に入り」**の最小アプリを作りながら、Next.js の基本を一気に通します。外部APIは使わず、ローカルの疑似データで完結させます。
0) プロジェクト作成
npx create-next-app@latest nextjs-intro-handson
cd nextjs-intro-handson
npm run dev
ブラウザで http://localhost:3000 を開いて動作確認します。
1) ルーティング:ページを増やす
app/ 配下にページを作ります。
app/about/page.tsx
export default function AboutPage() {
return (
<main style={{ padding: 24 }}>
<h1>About</h1>
<p>これは Next.js 入門ハンズオンの About ページです。</p>
</main>
);
}
これで /about にアクセスできるようになります。
Next.js 入門の最初の成功体験は、「ルーティングが自然に生える」ことです。
2) 疑似データを用意する(サーバー側で読む前提)
app/_data/posts.ts
export type Post = { slug: string; title: string; body: string };
export const posts: Post[] = [
{ slug: "hello-next", title: "Hello Next.js", body: "Next.js の世界へようこそ。" },
{ slug: "routing-basics", title: "Routing Basics", body: "app/ ディレクトリでルーティングします。" },
{ slug: "server-client", title: "Server vs Client", body: "必要なところだけ 'use client' にします。" },
];
_data は慣例的に「ルートではない補助フォルダ」として扱いやすいです(URL にならない)。
3) 一覧ページを作る(Server Component で表示)
app/posts/page.tsx
import Link from "next/link";
import { posts } from "../_data/posts";
export default function PostsPage() {
return (
<main style={{ padding: 24 }}>
<h1>Posts</h1>
<ul>
{posts.map((p) => (
<li key={p.slug}>
<Link href={`/posts/${p.slug}`}>{p.title}</Link>
</li>
))}
</ul>
</main>
);
}
これで /posts に一覧が出ます。
この時点ではクリックは Link に任せていて、自前の状態管理はゼロ。それでもアプリとして成立します。
4) 動的ルートで詳細ページ([slug])
app/posts/[slug]/page.tsx
import { posts } from "../../_data/posts";
import { notFound } from "next/navigation";
type Props = { params: { slug: string } };
export default function PostDetailPage({ params }: Props) {
const post = posts.find((p) => p.slug === params.slug);
if (!post) return notFound();
return (
<main style={{ padding: 24 }}>
<h1>{post.title}</h1>
<p>{post.body}</p>
</main>
);
}
notFound() が Next.js っぽいポイントで、存在しない slug の時に 404 として扱えます。
5) “操作が必要な部品だけ” Client Component 化する
ここから「お気に入り」ボタンを追加します。クリックが必要なので Client Component にします。
app/posts/[slug]/FavoriteButton.tsx
"use client";
import { useEffect, useState } from "react";
export default function FavoriteButton({ slug }: { slug: string }) {
const key = `fav:${slug}`;
const [fav, setFav] = useState(false);
useEffect(() => {
setFav(localStorage.getItem(key) === "1");
}, [key]);
const toggle = () => {
const next = !fav;
setFav(next);
localStorage.setItem(key, next ? "1" : "0");
};
return (
<button type="button" onClick={toggle} style={{ padding: "8px 12px" }}>
{fav ? "★ お気に入り解除" : "☆ お気に入り"}
</button>
);
}
そして詳細ページに組み込みます。
app/posts/[slug]/page.tsx(追記)
import FavoriteButton from "./FavoriteButton";
<FavoriteButton slug={post.slug} />
ここが Next.js の気持ちいいところで、
ページ全体は Server(軽い)、**ボタンだけ Client(操作)**という分割が自然にできます。
6) レイアウトを共通化する(layout.tsx)
ページごとの余白やヘッダーを揃えたいので、共通レイアウトを作ります。
app/layout.tsx
import Link from "next/link";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ja">
<body>
<header style={{ padding: 16, borderBottom: "1px solid #ddd" }}>
<nav style={{ display: "flex", gap: 12 }}>
<Link href="/">Home</Link>
<Link href="/about">About</Link>
<Link href="/posts">Posts</Link>
</nav>
</header>
<div style={{ padding: 24 }}>{children}</div>
</body>
</html>
);
}
これで全ページにナビが付き、アプリっぽさが一段上がります。
まとめ
Next.js 入門で押さえるべき要点は、結局のところ次の3つに集約されます。
- ルーティングは
app/とpage.tsxの規則で覚える(フォルダが URL になる) - Server / Client の分担が設計の中心(操作が必要な部品だけ
'use client') - データ取得はまず Server で考える(初期表示が強く、SEO/速度も取りやすい)
ハンズオンでは、一覧→詳細→お気に入りという“それっぽいアプリ”を、過剰なライブラリなしで組み立てました。Next.js の学習は、最初に 「分割の感覚」 を掴むと一気に楽になります。
「全部 Client にする」でも動きますが、Next.js の良さは薄れます。まずは 必要最小限だけ Client を癖にすると、その後の拡張(認証・DB・キャッシュ)も自然に繋がります。
コメントを残す