2025-11-24
勉強中メモ
gaaamii.icon
最近のNext.jsがさっぱりわからないのでChatGPTにいろいろ教えてもらった(以下は今日勉強したことの整理)
App Router / ルーティング構成
app/(site):公開側(閲覧用)
/ → app/(site)/page.tsx
/about → app/(site)/about/page.tsx
/posts/:id → app/(site)/posts/[id]/page.tsx
app/posts/(editor):投稿・編集用(書く側)
/posts/new → app/posts/(editor)/new/page.tsx
/posts/:id/edit → app/posts/(editor)/[id]/edit/page.tsx
layout.tsx でエディタ専用レイアウトを共有
app/admin:管理画面
/admin → app/admin/(dashboard)/page.tsx
/admin/posts/:id → app/admin/posts/[id]/page.tsx
route.ts は API/エンドポイント用(JSONやRSSなど)
page.tsx は 画面(Reactコンポーネント→HTML)用
Server Actions のポイント
フロントからサーバー関数を「普通の関数」のように呼べる仕組み
<form action={serverAction}> や await serverAction(data)
HTTPステータスや fetch をあまり意識せずに、
成功 → redirect() / データ返却
失敗 → エラー state を返す / 例外を投げる
というレベルで書ける
ただし「外部公開API」や「ステータスコードが重要な場面」は
依然として route.ts(Route Handler)側の責務
型安全に使う設計アイデア
ドメイン層で Zod スキーマ+型を定義
code:ts
const PostInputSchema = z.object({ title: z.string(), body: z.string() });
type PostInput = z.infer<typeof PostInputSchema>;
Server Action は PostInput を受け取り、Zodで parse してからDB処理
クライアント側は PostInput 型でオブジェクトを組み立てて createPost(input) を呼ぶので、
フィールド名の typo や抜けがコンパイル時に検知される
Zod + useFormState でのエラー表示
Server Action側:
FormData を受け取る
Zod.safeParse() → 失敗したら fieldErrors / formError を詰めた state を返す
クライアント側:
const [state, formAction] = useFormState(action, initialState)
<form action={formAction}> にして state.fieldErrors.title などを見て input 下にエラー文を表示
useFormStatus を組み合わせると、送信中のボタン無効化も簡単
認証まわり(Server ActionsとCookie)
ブラウザ → Server Action へのリクエストには、通常のHTTPルールでクッキーが自動で付く
Action 内で cookies() / headers() や auth() / getServerSession() を使って
「このリクエストは誰か?」を判定する
外部APIへの認証は、Server Action 内で fetch にトークンを付けて叩く(サーバー→外部API)
Nuxt 側の近い仕組み
コアに Next の Server Actions と同じものはない
代わりに:
Nuxt Form Actions(公式モジュール):フォーム → server/actions/*.ts の関数
nuxt-server-fn(コミュニティ):server/functions/*.ts をクライアントから関数として呼ぶ
組み合わせると「Server Actions っぽい」体験は作れる
やったこと
gaaamii.icon
Server Actions 触ったことなかったけどかなりよさそう。サーバー/クライアントでデータの型を共有して型安全にするの良い。OpenAPIやらジェネレータやらを使わず、普通に型定義とバリデーションスキーマを書けば良い、となるので良い。使いたくなった。