8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

最近、ChatGPTやClaudeに「Webアプリ作って」とお願いすると、返ってくるコードがだいたいNext.jsなんですよね。それで「Next.jsってなんだ?」と気になって調べ始めた人、けっこう多いんじゃないかと思っています。

ただ、いざ公式ドキュメントを開くと情報量が多くて、どこから手をつければいいのか分からなくなる。僕も最初はそうでした。(一応公式Docs貼っておきます)

この記事では、「全部完璧に理解する」のは一旦置いておいて、今からNext.jsを触るなら、最低限ここだけ押さえておけば動かせるというラインを実際にコード書きながらやっていきます。Reactをほとんど触ったことがない人も対象なので、Reactの話も軽くやっていきます。

Gemini_Generated_Image_wwu39ywwu39ywwu3.png

この記事の対象者

  • サクッとNext.jsを学びたい
  • なんとなくNext.js使っている
  • なんとなくReact使っている
  • Web系の土台の力つけたい

Next.jsとは何か

Next.jsは、ReactをベースにしたWebアプリ開発フレームワークです。Vercel社が開発していて、2026年6月時点では16系が最新で、新規プロジェクトは後述の「App Router」というもので始めるのが標準になっています。

Reactは画面(UI)を作るための部品でしかなく、ページの切り替え(ルーティング)やサーバー側の処理、ビルドの最適化などは自分で揃える必要がありました。Next.jsはそのあたりを最初からひとまとめにしてくれている、Webアプリを作る上で必要なものがセットに最適化されているというのが一番の特徴です。

今回ここは深掘りしませんが「React + Webアプリとして必要な道具を足したもの」くらいの理解で、一旦OKです。

Reactをおさらいする

Next.jsの土台はReactなので、'ここだけは'というポイントを先に押さえておきます。逆に言うと、Reactでつまずく人の多くはこの4つで止まっている印象なので、ここをざっくり掴めれば後がだいぶ楽になります。

コンポーネント

Reactでは画面を「コンポーネント」という部品の組み合わせで作ります。よーくみると、見た目を返す関数になっています。

// ボタンという部品
function LikeButton() {
  return <button>いいね</button>;
}

この LikeButton を他の場所で <LikeButton /> と書くと、ボタンが表示されます。こういったように部品を作って、他で使って組み合わせていく。これがReactの基本姿勢です。

JSX / TSX

さっきの return の中にHTMLみたいなものが混ざっていましたが、あれが JSX です。JavaScriptの中にHTMLっぽい書き方を埋め込める記法、くらいの理解でいいです。
また同じようにTypeScriptの中にHTMLっぽい書き方を埋め込める記法で TSX があります。ほとんどにてJavaScriptよりTypeScriptを選択するので TSX が主流というイメージでOKです。
※厳密には型定義して安定性を担保できるのでTSXが選ばれています。以降、TSXでの解説をしていきます。

注意点は2つだけ。クラス指定は class ではなく className と書くこと。そして、波カッコ {} の中にはJavaScriptの値を埋め込めること。

function Greeting() {
  const name = "やむぅ";
  return <p className="greeting">こんにちは、{name}さん</p>;
}

props(部品に値を渡す)

部品は、外から値を受け取って表示を変えたりできます。この受け取る値が props です。

function Greeting({ name }: { name: string }) {
  return <p>こんにちは、{name}さん</p>;
}

// 使う側
<Greeting name="やむぅ" />;

関数に引数を渡す感覚とほぼ同じです。

useState(状態を持つ)

ボタンを押したら数字が増える、みたいに「変化する値」を扱うときに使うのが useState です。

import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0); // 初期値0
  return <button onClick={() => setCount(count + 1)}>いいね {count}</button>;
}

count が今の値、setCount が値を更新する関数です。setCount で値を変えると、その部分の表示が自動で書き換わります。Reactは「状態が変わったら画面を作り直す」という仕組みで動いていて、この感覚さえ掴めれば十分です。

ここまでがReactの最低ライン。これを土台にNext.jsを触っていきます。

インストールしてみる

まずはNext.jsを使うための準備を解説します。まずNextを使っていくプロジェクトを作ります。Node.jsが入っている前提で、ターミナルで次を実行します。

npx create-next-app@latest

実行するといくつか質問されます。僕は基本こう答えてます。

プロジェクトの名前は?         → ここに好きな名前入れる(今回は「my-app」とする)
TypeScript を使う?           → Yes(型があるとAIの出力も読みやすい)
ESLint を使う?               → Yes
Tailwind CSS を使う?         → Yes(後述。最初はこれが楽)
src/ ディレクトリを使う?     → No
App Router を使う?           → Yes(ここは必ずYes)
Turbopack を使う?            → Yes
import alias をカスタムする? → No(デフォルトの @/* でいい)

作り終わったら、新しくフォルダーができます(僕の場合my-appができました)。そしたらできたフォルダに入って起動させます。

cd my-app
npm run dev

ブラウザで http://localhost:3000 を開いて初期画面が出れば成功です。

スクリーンショット 2026-06-10 15.09.42.png

これで「Next.jsで作ったデフォルトのwebアプリ」を開くことができました。
ここから先は、この app/ フォルダの中をいじっていきます。

こちら公式情報です。
https://nextjs.org/docs/app/getting-started/installation

まず全体像:押さえる概念はこれだけ

細かい話に入る前に、この記事で扱う範囲をざっと並べておきます。今は「そんなのあるんだ」でOKです。次の章から1つずつ実際にやりながら解説します。

概念 ひとことで言うと
App Router app/ にファイルを置く今の標準のやり方
ファイルベースルーティング フォルダ構成がそのままURLになる
Server / Client コンポーネント サーバーで動く部品とブラウザで動く部品の使い分け
データ取得 Serverコンポーネントの中で直接データを取りに行く
Server Actions フォーム送信などのデータ更新をサーバー側で書く
特別なファイル loading.tsx など名前で役割が決まるファイル
状態管理 変化する値の持ち方。最初は useState で十分
スタイリング 見た目の付け方。Tailwindで始めるのが楽

では、順にやっていきましょう。

App Routerとファイルベースルーティング

Next.jsで最初に「おっ」となるのがここです。フォルダとファイルを置く場所が、そのままURLになります。ルーティングの設定ファイル(どのパスでどんなページを表示するか)を書く必要がありません。

ルールはシンプルで、app/ の中に page.tsx という名前のファイルを置くと、その場所がページになります。

app/
├─ page.tsx          →  /        (トップページ)
├─ about/
│   └─ page.tsx      →  /about
└─ posts/
    └─ page.tsx      →  /posts

このQiitaでイメージしてもらうといいかなと思って、

  • トップページ(qiita.com)
    スクリーンショット 2026-06-10 15.23.21.png
  • マイページ(qiita.com/yamu_official)
    スクリーンショット 2026-06-10 15.21.44.png
  • 記事ページ(qiita.com/yamu_official/items/...)
    スクリーンショット 2026-06-10 15.21.36.png

このようにどのURLに載せる内容かを設定することができます。
試しに app/about/page.tsx を作ってみます。

page.tsx
// app/about/page.tsx にこれを置く
// このファイルを置いただけで /about にアクセスできる
export default function AboutPage() {
  return <h1>このサイトについて</h1>;
}

保存して http://localhost:3000/about を開くと表示されます。ただapp/aboutという場所にファイルを置いただけでそのページを作ることができました。

URLの一部を変数にしたいとき

/posts/1」「/posts/2」みたいに、URLの一部が変わるページを作りたくなる時があります。Qiitaでいう「ユーザーごとのプロフィール」や「記事ページ」など。その場合はフォルダ名を角カッコで囲みます。

app/posts/[id]/page.tsx   →  /posts/1, /posts/2, ...

このURLの id の部分は、params という形で受け取れます。今回でいうとこのparamsのidによって内容を変えたりできるようになります。注意として今のNext.js(15以降)では paramsawait してから使うのがポイントです。ここは初見だと戸惑うところなので、こういう形だと覚えてしまってOKです。

page.tsx
// app/posts/[id]/page.tsx
export default async function PostPage({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;
  return <h1>記事 {id} のページ</h1>;
}

これで /posts/5 にアクセスすると「記事 5 のページ」と出ます。

コンポーネントの2種類と使い分け

ここがNext.jsで一番大事で、最初につまずきやすいところです。Next.jsのコンポーネントには ServerコンポーネントClientコンポーネント の2種類があります。

Gemini_Generated_Image_czbp1tczbp1tczbp.png

使い分けの目安はこれだけ覚えておけば大丈夫です。

  • Serverコンポーネント(デフォルト):データを取ってきて表示するだけのページ、文章や一覧の表示など。大半はこっちで済みます。
  • Clientコンポーネント("use client"useState を使う、ボタンを押して何か変える、入力フォームを操作する、といった「動き」が要るとき。

さっきのReactのおさらいで出てきた Counter は、useState を使っていたので Clientコンポーネントになります。

// app/components/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>;
}

逆に、ただ表示するだけのページに "use client" は要りません。迷ったらまずServerのまま書いて、動きが必要になった部分だけ小さくClientに切り出す。僕はこの順番で考えるのをおすすめします。

結論、何も書かなければServerコンポーネントになります。そして、ボタンのクリックや入力など「ブラウザ側での動き」が必要なときだけ、ファイルの先頭に "use client" と書いてClientコンポーネントにします。

※パーツとしてのコンポーネント(今回でいうカウンターとかボタンとか)は基本的に/componentsフォルダーに置きますがapp/components/フォルダーに配置してもOKです。

データの取得

Serverコンポーネントの一番おいしいところがこれです。コンポーネントの中で直接データを取りに行けます。しかも関数を async にして await で待つだけ。専用の仕組みを覚える必要がありません。

試しに、サンプルAPIから記事一覧を取って表示してみます。

// app/posts/page.tsx (Serverコンポーネント。"use client" は書かない)
export default async function PostsPage() {
  // よく使われているサンプルとしてこれを↓使ってみてください: https://jsonplaceholder.typicode.com/posts
  const res = await fetch("なんかデータをとってくるAPI"); 
  const posts: { id: number; title: string }[] = await res.json();

  return (
    <ul>
      {posts.slice(0, 5).map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

/posts を開くと、APIから取った記事タイトルが5件並びます。このデータ取得はサーバー側で実行されるので処理的にも安定します。またAPIキーのような見せたくない情報もブラウザに漏れ図に処理できるのも特徴です。正直、Clientコンポーネントにして useEffect を使ってデータを取っていたReact従来のやり方もありますがロードくっそ遅くなります。

map で配列を回すときは key を付けるのを忘れずに。これはReact(HTMLの時でも)共通のお作法です。

データの更新:Server Actions

表示はできるようになりました。次によくあるのが「フォームから送信してデータを更新する」です。ここで使うのが Server Actions です。

ざっくり言うと、ボタンを押したらサーバー側で動く関数を、APIとかに頼らずそのまま書ける仕組みです。関数の先頭に "use server" と書くのが目印です。

まず、サーバー側で動く関数を用意します。

actions.ts
// app/posts/actions.ts
"use server";

import { revalidatePath } from "next/cache";

export async function addPost(formData: FormData) {
  const title = formData.get("title") as string;

  // 本来はここでDBに保存する。今は動きの確認なのでログだけ
  console.log("保存するタイトル:", title);

  // 一覧ページのデータを最新化する
  revalidatePath("/posts");
}

※つくてみると、今までのpage.tsxではないので/posts/actionsというパスを開いてもページは表示されません。
次に、この関数をフォームの action に渡します。

page.tsx
// app/posts/new/page.tsx
import { addPost } from "../actions";

export default function NewPostPage() {
  return (
    <form action={addPost}>
      <input name="title" placeholder="記事のタイトル" />
      <button type="submit">追加する</button>
    </form>
  );
}

これだけで、送信時にサーバー側の addPost が動きます。従来の fetch でAPIを叩くコードも、APIのエンドポイントを別に作る作業も要りません。フォームとサーバー処理が素直につながるのがServer Actionsの気持ちいいところです。

最初は「サーバーで動く関数を、フォームにそのまま渡して結びつけれる」という感覚だけ持っておけば十分です。

特別なファイル(loading.tsx とか)

Next.jsには、ファイル名が決まっていて、置くだけで役割を持つファイルがいくつかあります。代表的なものだけ押さえます。

一番よく使うのが loading.tsx です。同じフォルダに置くと、そのページのデータ読み込み中に自動で表示してくれます。ローディングの出し分けを自分で書かなくていい、というのが便利なところです。

// app/posts/loading.tsx
export default function Loading() {
  return <p>読み込み中です…</p>;
}

さっきの /posts はAPIからデータを取っていたので、読み込みの間だけこの「読み込み中です…」が出るようになります。

他にも、名前で役割が決まるファイルがあります。最初は名前と役割だけ知っておけば十分です。

  • layout.tsx:複数ページで共通の枠(ヘッダーやフッターなど)を設定できる
    • app/layout.tsx は全ページ共通の土台で、最初から入っている
  • error.tsx:エラーが起きたときに表示する画面
  • not-found.tsx:ページが見つからないとき(404)の画面

「ローディングやエラーの画面は、決まった名前のファイルを置けば差し込まれる」。この発想を知っておくと、後々楽になります。

状態管理は、最初は欲張らない

「状態管理」と聞くと「んっ。」となるかもしれませんが、最初は useState だけで十分です。最初はこれだけでOKです。

変化する値が1つの部品の中で完結するなら useState。親から子へ値を渡したいなら props。ここまではReactのおさらいでやった範囲でこと足ります。

「離れた場所同士で同じ値を共有したい」となったとき初めて、useContext や、ZustandやJotaiといった状態管理ライブラリの出番になります。だけどここで知っておいてほしいのは、Serverコンポーネントでサーバーから直接データを渡せるようになった分、昔ほどいろんなところ行き来するクライアント側の状態管理は要らなくなっているということです。

なので僕の基本方針は「状態管理ライブラリは最初から入れない」。必要になって、本当に困ってから足す。先回りして複雑にしちゃって頭パンクすると本末転倒です。

スタイリング:Tailwindで始める

見た目の付け方です。Next.jsでは主に3つのやり方があります。

一つ目が Tailwind CSSclassName にあらかじめ用意されたクラス名を並べて、その場でスタイルを当てていく方式です。create-next-app で「Yes」にしていればデフォで使えます。

export default function Card() {
  return (
    <div className="rounded-lg border p-4 shadow">
      <h2 className="text-xl font-bold">タイトル</h2>
      <p className="mt-2 text-gray-600">説明文がここに入ります。</p>
    </div>
  );
}

text-xl(文字大きめ)、font-bold(太字)、p-4(余白)のように、クラス名を見れば何のスタイルか想像がつきます。別のCSSファイルを行ったり来たりしなくていいので、今から始めるならまずこれが楽です。

公式を見ながら使っていきましょう。

残り2つも軽く触れておきます。

  • グローバルCSSapp/globals.css に普通のCSSを書く方式。サイト全体の共通スタイルはここに置きます(最初から存在します)。
  • CSS ModulesCard.module.css のようなファイルを作って、その部品専用のスタイルを書く方式。クラス名の衝突を気にせず書けます。

僕の今のおすすめは、Tailwindで全体を組んで、どうしても細かく調整したいところだけCSS Modulesに置いとくやり方です。CSS Modulesは滅多に使いません。最初からあれこれ混ぜると管理がしんどくなるので、Tailwind一本で始めて困ったら足す、で十分です。

まとめ

駆け足でしたが、今からNext.jsを動かすうえで「ここだけは」というラインを通してきました。最後に要点だけ振り返ります。

  • Next.jsは ReactにWebアプリ用の道具を足したフレームワーク。今から始めるなら App Router 一択。
  • ルーティングは ファイルを置く場所がそのままURL。設定はいらない。
  • コンポーネントは デフォルトがServer。動きが必要な部分だけ "use client"
  • データ取得は Serverコンポーネントの中で async/await するだけ
  • データ更新は Server Actions"use server")でフォームと素直につながる。
  • loading.tsx など 名前で役割が決まる特別なファイルがある。
  • 状態管理とスタイリングは 欲張らないuseState とTailwindで始めて、困ってから足す。

全部を完璧に理解してから動かそうとすると、たいてい途中で止まります。それより、まず手元で動かして「あ、こういうことか」を増やしていくほうが、結果的に早いです。この記事で作ったページをいじり倒すところから始めてもらえたらと思います。

冒頭に書いたとおり、これからの時代はAIがNext.jsのコードを書いてくれる場面が増えます。だからこそ、ここで押さえた「どこに何があるか」の地図が、AIの出したコードを読んで直すときにそのまま効いてきます。

自己紹介

現在、8年目になるエンジニア兼PMやってるやむぅ。です!普段はフリーランスエンジニアとして、8人の開発チームのPM(プロジェクトマネージャー)をしたり、AIゲームコーチングサービス『Repl-AI』などの「個人サービス運営」「個人的なエンジニアサポート」この三つを主軸に活動しています。

  • エンジニア歴: 8年目(上流の設計から下流の実装・テストまで全部やってます)
  • 得意な技術: Java, TypeScript, Next.js, Python, Go, Cursor, Claude codeなど
  • 個人運営スクール: 個人開発や転職にコミットするプログラミングスクール「Programing Factory - ProFact」運営
  • 個人開発したサービス運営: 
    • WebニュースのAI分析サービス
    • Twitchクリップの検索・シェアサイト
    • Meta社のThreads分析・投稿予約ツール
    • ゲームプレイのAIコーチングサービス
      他にも、YouTubeをNuxt x FastAPI x MySQLで作ってみたり、SNSでプログラミングに関することを話してたりもします。

僕がやっているProFactでは、こういう「AIと一緒に開発する前提の実務スキル」を現役エンジニアと一緒に手を動かしながら学べます。気になった方はのぞいてみてください。

※副業、Web制作を目指している方はお力になれません…ご了承ください。

参考(一次ソース):

8
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?