最終更新:

Next.jsの始め方 — お店のページと、クリックできるボタンを作ろう


画面、API、ボタンの役割を分ける

ひよこのお店/shop の画面りんごは 200円0回押しました画面:page.tsx商品API:route.tsボタン:Clientの部品
本文の三つのファイルと対応。use clientはモジュールの境界であり、初回表示のHTMLがサーバーで作られないという意味ではありません。
🎚 難易度 ★★☆ 中級者向け
⏱ 学習時間の目安 読むだけ10分程度。練習時間は環境で変わります。
📚 前提知識 react-getting-started の基礎知識・typescript-getting-started(推奨)
✅ このガイドで学べること
  • App Routerのお店ページ
  • Clientの数えるボタン
  • 固定商品API
  • ビルドと公開の区別
ひよこ ひよこ
Reactで小さな画面を作れたよ。Next.jsでは何が増えるの?
ペンギン先生 ペンギン先生
ページのルーティングやサーバー側の処理などをまとめるReactフレームワークだよ。今回はお店のページ、商品を返すAPI、数えるボタンの三つを、小さなプロジェクトで試そう。
ひよこ ひよこ
何を準備すればいい?
ペンギン先生 ペンギン先生
Node.jsとnpm、Reactの基礎。新しいApp Routerプロジェクトを作る。質問や既定設定は版によって変わるので、本文ではTypeScript・app直下などの設定を指定するよ。
ひよこ ひよこ
ページを増やすのは難しい?
ペンギン先生 ペンギン先生
app/shop/page.tsxなら/shopのページになる。pageは画面、layoutは共通の包み。ファイルの配置とURLを結び付けると分かりやすいよ。
ひよこ ひよこ
Server Componentは何?
ペンギン先生 ペンギン先生
App Routerのページやレイアウトは既定でServer Component。サーバー側でデータを読むなどの役割を持つ。ブラウザーのイベントや状態が必要な部分はClient Componentに分けるよ。
ひよこ ひよこ
use clientを書くと、サーバーでは一切動かない?
ペンギン先生 ペンギン先生
そうではない。最初の表示ではClient ComponentもサーバーでHTMLに事前描画され、ブラウザーで操作できる状態になる。use clientはクライアント側モジュールとの境界を宣言するものだよ。
ひよこ ひよこ
商品のJSONも返せる?
ペンギン先生 ペンギン先生
app/api/product/route.tsでGETをexportすると、そのURLのRoute Handlerになる。ページと同じURLの階層へpageとrouteを重ねない。固定の商品から試してみよう。
ひよこ ひよこ
force-cacheならSSG、no-storeならSSRと覚えればいい?
ペンギン先生 ペンギン先生
それだけでは足りないよ。データのキャッシュ、ルートの生成、実行時データ、Cache Componentsの設定は別の観点。使う版と設定をそろえて公式の説明を読む。
ひよこ ひよこ
作れたらそのまま公開できる?
ペンギン先生 ペンギン先生
まずローカルで表示とボタン、APIを確認し、buildを実行する。Node.jsサーバー、Docker、静的出力などは使える機能が異なる。公開環境、秘密、入力検証と権限を確認して次へ進もう。

まず、新しいお店のページを作る

Reactの基礎と、サポート中のNode.js LTS、npmを用意します。Next.jsの最低要件はNode.js 20.9以上ですが、テンプレート・依存の条件も確認します。この例はNode.js 24で確認しました。

新しいフォルダーを作る例です。長いコマンドは一行で実行します。Cache Componentsなどの高度な設定を最初の練習には加えません。

npx create-next-app@latest next-shop-demo --typescript --app --no-tailwind --no-src-dir --no-linter --no-react-compiler --no-cache-components --use-npm --yes
cd next-shop-demo

app/shop/page.tsxを作ります。

import Counter from './counter';
export default function Shop() {
  return (
    <main>
      <h1>ひよこのお店</h1>
      <p>りんごは200円です。</p>
      <Counter />
    </main>
  );
}

app/shop/counter.tsxを作ります。

'use client';
import { useState } from 'react';
export default function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      {count}回押しました
    </button>
  );
}

npm run devを実行し、端末に出たURLの/shopを開きます。お店の見出しと、押すたびに数が増えるボタンが出れば成功です。

商品APIも一つ作る

app/api/product/route.tsを作ります。

export function GET() {
  return Response.json({
    name: 'りんご',
    price: 200,
  });
}

同じサーバーの/api/productを開き、JSONを確認します。今回は固定の商品で、DB、ログイン、外部APIを使いません。

ファイルと役割を整理する

次のファイルは、すべてapp/の下です。

ファイル役割
shop/page.tsx/shopの画面
shop/counter.tsx状態とクリックの処理
api/product/route.ts/api/productの応答
layout.tsx共通のレイアウト

Server ComponentとClient Componentは、サーバーという機械と利用者の端末を単純に二分する名前ではありません。最初のHTMLの表示と、ブラウザーでの操作を区別して読むと理解しやすくなります。

ビルドと公開は別の段階

開発サーバーをCtrl+Cで止めてからnpm run buildを試します。Node.jsサーバーとして試す場合は、その後npm run startで起動し、端末のURLを確認します。終わったらCtrl+Cで止めます。

本番へ出す際は、公開先と利用機能を選びます。静的出力には機能の制限があり、サーバーで動くRoute Handlerなどを同じように使えるとは限りません。

もう少し詳しく:キャッシュと変更処理

fetchのキャッシュ、ルートの静的・動的生成、再検証は関連しますが同じものではありません。force-cacheだけをSSGの指定だと覚えず、Next.jsの版とCache Componentsの設定をそろえて確認します。

注文を保存する機能へ広げるなら、Server ActionsやRoute Handlerでも、入力検証と認証・認可が必要です。サーバーで動くことだけで権限が正しく守られるわけではありません。

ペンギン先生のまとめ

「Next.js」って出てきたら「Reactの画面に、ページの道筋やサーバー側の処理を加える枠組み」と思えばだいたいOK! まずお店の画面、ボタン、商品APIの役割を説明してみよう。

参考資料

次に学ぶなら