Web系初心者がNext.jsでお問い合わせフォームを作ろうとして2時間くらいつまづいたときの忘備録です。
背景
自社のコーポレートサイトをシングルページアプリケーション(SPA)化しようと取り組んでいました。
実装が簡単らしいということでNext.jsを採用しました。
その中で、「お問い合わせフォーム」の送信データを処理するためにNext.jsのAPIルートを活用しようとしました。
しかし、うまく動作せず2時間くらい原因がわからずつまづきました。
何が問題だったか
APIエンドポイント(/api/submitContact
)にリクエストを送信すると、常に 404エラー が返ってきました。
具体的には、フォーム送信後にブラウザのコンソールに以下のエラーが表示されていました。
POST http://localhost:3000/api/submitContact 404 (Not Found)
一方、pages/api/submitContact.js
ファイルはプロジェクト内の正しいディレクトリに存在しており、ローカルサーバーで開発時には正常に動作していました。
試したアプローチ
問題の原因を探るため、以下のアプローチを試しました。
-
APIルートのパス確認
-
pages/api/submitContact.js
が正しい場所にあることを確認。 - URLのパスにタイポやスペルミスがないことを確認。
-
-
APIエンドポイントの直接アクセス
- ブラウザで
http://localhost:3000/api/submitContact
に直接アクセス。 - 開発環境では期待通りに動作し、404エラーは発生しませんでした。
- ブラウザで
-
ビルド後の動作確認
-
npm run build && npm start
で本番環境に近い状態を再現。 - この状態でも、404エラーは発生しませんでした。
-
-
デプロイ後の動作確認
- 実際のレンタルサーバー上にデプロイし、フォームを送信。
- 再び404エラーが発生。
原因究明
最終的に、Next.jsのoutput: export
設定が問題の原因であることが判明しました。
// next.config.mjs
const nextConfig = {
output: 'export', // 静的HTMLとしてエクスポートする設定
};
export default nextConfig;
デプロイとかの学習コストを下げるため静的HTMLで実装していたのですが、APIエンドポイントは静的エクスポートには含まれず、動作しなくなる仕様となっていました。
どう対応したか
以下の2つの対応策を検討しました。
APIルートを使用しない方法への切り替え
Next.jsのAPIルートの代わりに、従来のPHPスクリプトをサーバー上に配置してフォームデータを処理することにしました。
// submit_contact.php
<?php
$to = "info@example.com";
$subject = "お問い合わせ";
$message = "お名前: {$_POST['name']}\nメールアドレス: {$_POST['email']}\n内容: {$_POST['details']}";
$headers = "From: no-reply@example.com";
if (mail($to, $subject, $message, $headers)) {
header("Location: /thankyou.html");
exit();
} else {
header("Location: /error.html");
exit();
}
?>
Next.js側のフォーム送信コードの修正例:
<form action="/submit_contact.php" method="post">
<input type="text" name="name" required placeholder="お名前" />
<input type="email" name="email" required placeholder="メールアドレス" />
<textarea name="details" required placeholder="お問い合わせ内容"></textarea>
<button type="submit">送信</button>
</form>
別案:SSRへの切り替えを断念
静的エクスポート(output: export)をやめて、APIルートをサポートするSSRに切り替えることも検討しました。しかし、現行のホスティング環境がSSRをサポートしていないため、今回は断念しました。
結果
PHPスクリプトを使用したフォーム送信に切り替えた結果、レンタルサーバー上でもフォームデータを正しく処理できるようになりました。
まとめ
静的エクスポートを使用する場合、Next.jsのAPIルートは利用できなくなるという仕様に気づかず原因究明に時間がかかりました。