NextJS 14生产环境API接口404,本地运行正常
NextJS 14生产环境/api/sendEmail接口404问题排查
我用NextJS 14搭建了一个小型网站,包含联系我们页面。在GetInTouch.tsx中基于Formik实现了表单验证与提交逻辑,提交时调用/api/sendEmail接口;pages/api目录下有sendEmail.ts文件,使用Mailtrap发送邮件。本地测试时表单验证和邮件发送均正常,但部署到生产环境后,始终提示mydomain.com/api/sendEmail不存在,作为NextJS新手无法定位问题所在。
GetInTouch.tsx代码
<Formik initialValues={{ fullName: "", phoneNumber: "", email: "", message: "", }} validationSchema={Yup.object({ fullName: Yup.string().required("Required"), phoneNumber: Yup.string().required("Required"), email: Yup.string() .email("Invalid email address") .required("Required"), message: Yup.string().required("Required"), })} onSubmit={async (values, { setSubmitting, resetForm }) => { try { const response = await fetch("/api/sendEmail", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(values), }); if (!response.ok) { throw new Error("Failed to send email"); } setShowSuccessMessage(true); setTimeout(() => { setShowSuccessMessage(false); }, 5000); resetForm(); } catch (error) { console.error("Error sending email:", error); } finally { setSubmitting(false); } }} > {(formik) => ( <Form> <div className="pb-3"> <Field type="text" name="fullName" placeholder="Full Name" className="form-input space-y-2 pt-15px lg:pt-20px w-full h-12 px-5 py-10px placeholder-white text-white" style={{ backgroundColor: '#0c3863',border: '1.5px solid white'}} /> <ErrorMessage name="fullName" component="div" className="text-red-600" style={{color: "red"}} /> </div> <div className="pb-3"> <Field type="text" name="phoneNumber" placeholder="Phone Number" className="form-input space-y-2 pt-15px lg:pt-20px w-full h-12 px-5 py-10px placeholder-white text-white " style={{ backgroundColor: '#0c3863',border: '1.5px solid white'}} /> <ErrorMessage name="phoneNumber" component="div" className="text-red-600" style={{color: "red"}} /> </div> <div className="pb-3"> <Field type="email" name="email" placeholder="Email" className="form-input space-y-2 pt-10px lg:pt-15px w-full h-12 px-5 py-10px placeholder-white text-white" style={{ backgroundColor: '#0c3863',border: '1.5px solid white'}} /> <ErrorMessage name="email" component="div" className="text-red-600" style={{color: "red"}} /> </div> <div className="pb-3"> <Field as="textarea" name="message" placeholder="Message" className="form-textarea w-full pt-15px lg:pt-20px placeholder-white px-5 py-30px text-white" style={{ backgroundColor: '#0c3863',border: '1.5px solid white'}} /> <ErrorMessage name="message" component="div" className="text-red-600" style={{color: "red"}} /> </div> <Button type="submit" disabled={formik.isSubmitting} className="btn" size={"large"} colorTheme={"blue1"} uppercase > Enquire now </Button> </Form> )} </Formik> {showSuccessMessage && ( <div className="success-message flex items-center text-white text-sm font-bold py-3" > Message sent successfully! </div> )} </div>
sendEmail.ts代码
import { NextApiRequest, NextApiResponse } from 'next'; import nodemailer from 'nodemailer'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method !== 'POST') { return res.status(405).end(); // Method Not Allowed } try { const { fullName, phoneNumber, email, message } = req.body; const transporter = nodemailer.createTransport({ host: 'sandbox.smtp.mailtrap.io', port: 2525, auth: { user: '543c2217cf0f8b', pass: '5rthae759cd4c0', }, }); await transporter.sendMail({ from: 'your-email@example.com', to: 'support@abc.com', subject: 'New contact form submission', html: ` <p>Full Name: ${fullName}</p> <p>Phone Number: ${phoneNumber}</p> <p>Email: ${email}</p> <p>Message: ${message}</p> `, }); res.status(200).json({ message: 'Email sent successfully' }); } catch (error) { console.error('Error sending email:', error); res.status(500).json({ error: 'An error occurred while sending the email' }); } }
问题排查与解决办法
- 路由目录不匹配:NextJS 14默认推荐App Router,若你用的是App Router模式,API路由需放在
app/api/sendEmail/route.ts(文件名必须是route.ts),且导出方式要调整为App Router的格式:import { NextResponse } from 'next/server'; import nodemailer from 'nodemailer'; export async function POST(request: Request) { const body = await request.json(); const { fullName, phoneNumber, email, message } = body; const transporter = nodemailer.createTransport({ host: 'sandbox.smtp.mailtrap.io', port: 2525, auth: { user: '543c2217cf0f8b', pass: '5rthae759cd4c0', }, }); await transporter.sendMail({ from: 'your-email@example.com', to: 'support@abc.com', subject: 'New contact form submission', html: ` <p>Full Name: ${fullName}</p> <p>Phone Number: ${phoneNumber}</p> <p>Email: ${email}</p> <p>Message: ${message}</p> `, }); return NextResponse.json({ message: 'Email sent successfully' }, { status: 200 }); } - 部署平台静态导出限制:若你在next.config.js中配置了
output: 'export'做静态导出,NextJS不会生成API路由,因为静态站点不支持服务器端逻辑。此时需去掉静态导出配置,或改用部署平台的Serverless函数替代NextJS API路由。 - 路径大小写敏感:生产环境服务器通常区分文件名大小写,确保
sendEmail.ts的文件名与请求路径/api/sendEmail完全一致(比如不要写成SendEmail.ts)。 - basePath配置影响:若next.config.js中设置了
basePath,请求API时需带上basePath,可通过环境变量动态拼接路径:const apiUrl = `${process.env.NEXT_PUBLIC_BASE_PATH || ''}/api/sendEmail`; const response = await fetch(apiUrl, { /* 其余配置 */ }); - 缓存问题:生产环境可能缓存了旧页面资源,强制刷新浏览器(Ctrl+Shift+R)或重新部署项目,确保最新代码生效。
内容的提问来源于stack exchange,提问作者user3391363
相关产品推荐
相关产品推荐

