
Linkコンポーネントによる画面遷移
はじめに 前回までにNext.jsのページコンポーネント作成方法を学びました。今回は、作成したページ間をシームレスに移動するための「Linkコンポーネント」につ […]
Next.jsはフロントエンドだけでなく、バックエンドAPIの作成もサポートしています。pages/api
ディレクトリにファイルを作成するだけで、簡単にAPIエンドポイントを作成できます。この記事では、Next.jsを使った基本的なAPIの作成方法を初心者向けに詳しく解説します。
Next.jsのAPIルートは、以下の特徴を持っています:
pages/api/hello.js
ファイルを作成:
// req = リクエストオブジェクト(受信データ)
// res = レスポンスオブジェクト(返信データ)
export default function handler(req, res) {
res.status(200).json({ message: 'Hello World!' });
}
このAPIは以下のようにアクセスできます:
http://localhost:3000/api/hello
https://yourdomain.com/api/hello
異なるHTTPメソッド(GET, POSTなど)に対応する:
export default function handler(req, res) {
if (req.method === 'GET') {
// GETリクエストの処理
res.status(200).json({ message: 'GETリクエストを受け取りました' });
} else if (req.method === 'POST') {
// POSTリクエストの処理
res.status(200).json({ message: 'POSTリクエストを受け取りました' });
} else {
// その他のメソッド
res.setHeader('Allow', ['GET', 'POST']);
res.status(405).end(`Method ${req.method} Not Allowed`);
}
}
URLのクエリパラメータ(?key=value
)を取得:
// /api/user?id=123 にアクセスした場合
export default function handler(req, res) {
const { id } = req.query; // { id: '123' }
res.status(200).json({ userId: id });
}
export default async function handler(req, res) {
if (req.method === 'POST') {
// ボディデータを取得
const data = req.body;
// データベースに保存などの処理...
res.status(200).json({
status: 'success',
data: data
});
}
}
// pages/api/users/[id].js - 動的APIルート
export default function handler(req, res) {
const { id } = req.query;
// 実際のアプリではデータベースから取得
const users = {
'1': { name: '山田太郎', email: 'taro@example.com' },
'2': { name: '佐藤花子', email: 'hanako@example.com' }
};
const user = users[id];
if (user) {
res.status(200).json(user);
} else {
res.status(404).json({ message: 'ユーザーが見つかりません' });
}
}
// pages/api/contact.js
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ message: 'POSTメソッドのみ許可されています' });
}
try {
const { name, email, message } = req.body;
// バリデーション
if (!name || !email || !message) {
return res.status(400).json({ message: 'すべてのフィールドが必須です' });
}
// 実際のアプリではここでメール送信やデータベース保存を行う
console.log('お問い合わせ内容:', { name, email, message });
return res.status(200).json({
status: 'success',
message: 'お問い合わせありがとうございます'
});
} catch (error) {
console.error('Error:', error);
return res.status(500).json({
message: 'サーバーエラーが発生しました'
});
}
}
// pages/api/proxy/weather.js
export default async function handler(req, res) {
const { city } = req.query;
try {
const apiKey = process.env.WEATHER_API_KEY;
const response = await fetch(
`https://api.weatherapi.com/v1/current.json?key=${apiKey}&q=${city}`
);
if (!response.ok) {
throw new Error('天気情報の取得に失敗しました');
}
const data = await response.json();
res.status(200).json(data);
} catch (error) {
res.status(500).json({
message: error.message
});
}
}
// pages/api/secret-data.js
export default function handler(req, res) {
// クライアントに公開したくないサーバーサイドのみの処理
const secretKey = process.env.SECRET_KEY;
const sensitiveData = doSomeSecureCalculation(secretKey);
res.status(200).json({
result: sensitiveData
});
}
function doSomeSecureCalculation(key) {
// クライアントサイドに公開したくない処理
return `Processed with ${key.substring(0, 4)}...`;
}
APIルートでミドルウェアを使用して、共通処理をまとめることができます。
// pages/api/with-cors.js
import Cors from 'cors';
// CORSミドルウェアを初期化
const cors = Cors({
methods: ['GET', 'HEAD'],
});
// ミドルウェアを実行するヘルパー関数
function runMiddleware(req, res, fn) {
return new Promise((resolve, reject) => {
fn(req, res, (result) => {
if (result instanceof Error) {
return reject(result);
}
return resolve(result);
});
});
}
export default async function handler(req, res) {
// CORSミドルウェアを実行
await runMiddleware(req, res, cors);
// APIロジック
res.json({ message: 'CORSが有効化されています' });
}
// utils/auth-middleware.js
export function withAuth(handler) {
return async (req, res) => {
// 認証トークンを確認
const token = req.headers.authorization?.split(' ')[1];
if (token !== process.env.API_TOKEN) {
return res.status(401).json({ message: '認証が必要です' });
}
// 認証成功したら元のハンドラーを実行
return handler(req, res);
};
}
// pages/api/protected.js
import { withAuth } from '../../utils/auth-middleware';
function handler(req, res) {
res.status(200).json({
secretData: 'これは認証が必要なデータです'
});
}
export default withAuth(handler);
APIルートでは適切なエラーハンドリングが重要です。
// utils/api-error.js
export class ApiError extends Error {
constructor(statusCode, message) {
super(message);
this.statusCode = statusCode;
}
}
// utils/handle-error.js
export function handleError(res, error) {
if (error instanceof ApiError) {
return res.status(error.statusCode).json({
message: error.message
});
}
console.error('Unexpected error:', error);
return res.status(500).json({
message: '予期せぬエラーが発生しました'
});
}
// pages/api/products/[id].js
import { ApiError } from '../../utils/api-error';
import { handleError } from '../../utils/handle-error';
export default async function handler(req, res) {
try {
const { id } = req.query;
if (!isValidId(id)) {
throw new ApiError(400, '無効なID形式です');
}
const product = await getProductFromDatabase(id);
if (!product) {
throw new ApiError(404, '製品が見つかりません');
}
res.status(200).json(product);
} catch (error) {
handleError(res, error);
}
}
GETリクエストはブラウザのアドレスバーに直接入力してテスト可能:http://localhost:3000/api/hello
# GETリクエスト
curl http://localhost:3000/api/hello
# POSTリクエスト
curl -X POST -H "Content-Type: application/json" -d '{"name":"John"}' http://localhost:3000/api/users
// Reactコンポーネント内
async function fetchData() {
try {
const response = await fetch('/api/hello');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
// POSTリクエストの例
async function postData() {
try {
const response = await fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'John' }),
});
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
Next.jsのAPIルートは以下の環境で実行されます:
APIルートで直接データベースに接続できます:
import { connectToDatabase } from '../../lib/mongodb';
export default async function handler(req, res) {
const { db } = await connectToDatabase();
const data = await db.collection('posts').find().toArray();
res.status(200).json(data);
}
Next.jsのAPIルートについて学びました。主なポイントは:
pages/api
ディレクトリにファイルを作成するだけでAPIエンドポイントが作成できるAPIルートは小規模なバックエンド処理やプロキシ、フォーム処理などに最適です。ただし、複雑なバックエンドシステムが必要な場合は、専用のバックエンドサービスと組み合わせることも検討しましょう。
Next.jsの公式ドキュメントも参考にしてください:
https://nextjs.org/docs/api-routes/introduction