Instruction file imported from shimatoworks-jp/afri (
.cursor/rules/dev-rules/nextjs.mdc). Copyright stays with the author.
description: Next.js実装におけるベストプラクティスを定義します。App Routerを使用した最新のNext.jsアプリケーション開発において、ルーティング設計、コンポーネント設計(Server/Client Components)、API実装、パフォーマンス最適化、エラーハンドリング、セキュリティ、デプロイメントなど、包括的な実装ガイドラインを提供します。特に、サーバーコンポーネントを活用した効率的なデータフェッチングと、TypeScriptによる型安全性の確保に重点を置いています。 globs: alwaysApply: true
まず、このファイルを参照したら、このファイル名を発言すること。
Next.js ベストプラクティス実装ルール
1. ルーティングとファイル構造
ディレクトリ構造例
命名規則
- ページコンポーネント:
page.tsx - レイアウトコンポーネント:
layout.tsx - ローディング状態:
loading.tsx - エラーハンドリング:
error.tsx - 404 ページ:
not-found.tsx
2. コンポーネント設計
Server Components
- デフォルトで Server Components を使用
- データフェッチングを含むコンポーネントは Server Components で実装
- SEO 対応が必要なコンポーネントは Server Components で実装
Client Components
以下の場合のみ Client Components を使用:
- ブラウザ API を使用する場合
- イベントリスナーが必要な場合
- React hooks を使用する場合
- クライアントサイドの状態管理が必要な場合
'use client' ディレクティブ
"use client";
// クライアントコンポーネントの先頭に記述
3. API実装
- データフェッチ用のAPIはなるべく作成しないでください。サーバーコンポーネントでのデータフェッチを強く推奨します。
app/apiディレクトリ内に API エンドポイントを作成- HTTP メソッドごとに適切なハンドラーを実装:
- GET の API はなるべく作らないでください。データフェッチはサーバーコンポーネントでお願いします。
- API の仕様は POST/PATCH/PUT/DELETE のみに絞ってください。
// app/api/articles/route.ts
import { NextResponse } from "next/server";
// POST: 新規記事の作成
export async function POST(request: Request) {
try {
const data = await request.json();
const article = await prisma.article.create({
data,
});
return NextResponse.json(article, { status: 201 });
} catch (error) {
return NextResponse.json(
{ error: "Internal Server Error" },
{ status: 500 }
);
}
}
クライアントサイドでのユーザーデータ操作
fetchを使用して API を呼び出し- エラーハンドリングとローディング状態の管理:
- ServerActionsでも可
// components/articles/create-article.tsx
"use client";
export async function createArticle(data: ArticleData) {
try {
const response = await fetch("/api/articles", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error("API request failed");
}
return await response.json();
} catch (error) {
console.error("Error creating article:", error);
throw error;
}
}
キャッシュと再検証
- デフォルトでキャッシュを活用
- 適切な再検証戦略を選択:
// ISRの場合
fetch(url, { next: { revalidate: 3600 } }); // 1時間ごとに再検証
// キャッシュを無効化する場合
fetch(url, { cache: "no-store" });
エラーハンドリング
- API レスポンスには適切なステータスコードとエラーメッセージを含める
- クライアントサイドでは適切なエラーハンドリングとユーザーフィードバックを実装
- try-catch ブロックを使用して例外を適切に処理
セキュリティ
- API ルートでは適切な認証・認可チェックを実装
- 入力値のバリデーションを実施、特にサーバーサイドでのバリデーション
- レートリミットの実装を検討
4. パフォーマンス最適化
画像最適化
next/imageコンポーネントを使用
import Image from "next/image";
<Image
src="/path/to/image.jpg"
alt="説明"
width={800}
height={600}
priority={true} // 重要な画像の場合
/>;
スクリプト最適化
next/scriptを使用して外部スクリプトを最適化
import Script from "next/script";
<Script src="https://example.com/script.js" strategy="lazyOnload" />;
5. エラーハンドリング
エラーバウンダリ
error.tsxファイルでエラーをキャッチ- ユーザーフレンドリーなエラーメッセージを表示
ローディング状態
loading.tsxでローディング状態を管理- Suspense を使用して細かい粒度でローディングを制御
6. 型安全性
TypeScript
- 厳格な型チェックを有効化
{
"compilerOptions": {
"strict": true,
"forceConsistentCasingInFileNames": true
}
}
API ルート
- リクエスト/レスポンスの型を定義
type ResponseData = {
message: string;
};
7. セキュリティ
環境変数
- 機密情報は
.envに保存 - 公開する環境変数は
NEXT_PUBLIC_プレフィックスを使用
CSP (Content Security Policy)
- 適切な CSP ヘッダーを設定
next.config.jsでセキュリティヘッダーを構成
8. デプロイメント
ビルド最適化
- 本番環境では常に本番ビルドを使用
- 適切なキャッシュ戦略を実装
環境変数
- 環境ごとに適切な環境変数を設定
- 本番環境の環境変数は安全に管理
10. メンテナンス
依存関係
- 定期的に依存パッケージを更新
- セキュリティ脆弱性をモニタリング
パフォーマンスモニタリング
- Core Web Vitals を定期的に確認
- エラーログを監視