Next.js API路由本地正常但生产环境提交评论报错求助
生产环境提交评论失败问题排查与修复
API路由代码问题与修复
原API路由存在以下几个核心问题,直接导致生产环境报错:
- 未捕获异步操作异常:Sanity的
create操作失败时会抛出错误,未处理的异常会让API返回500错误 - 未正确完成响应:仅设置
status(200)但未发送响应体,会导致请求挂起超时 - 未限制请求方法:未校验请求是否为POST,其他请求方法会引发错误
- Client初始化逻辑冗余:每次请求都重新配置client,应该在路由外初始化复用
修复后的API路由代码:
import client from '@sanity/client' // 全局初始化Sanity客户端,避免重复配置 const sanityClient = client({ projectId: process.env.SANITY_PROJECT_ID, dataset: process.env.SANITY_DATASET, apiVersion: '2023-05-03', useCdn: false // 写入操作禁用CDN }) export default async function CreateComment(req, res) { // 仅处理POST请求 if (req.method !== 'POST') { return res.status(405).json({ message: '仅支持POST请求' }) } try { const { name, comment, _id } = JSON.parse(req.body) await sanityClient.config({ token: process.env.SANITY_AUTH_TOKEN }).create({ _type: "comment", name, comment, blog:{ _type: "reference", _ref: _id }, }) return res.status(200).json({ success: true, message: '评论提交成功' }) } catch (error) { console.error('创建评论失败:', error) return res.status(500).json({ success: false, message: '评论提交失败', error: error.message }) } }
表单组件代码问题与修复
原表单组件的问题会导致生产环境下请求未完成就刷新,或无法感知请求失败:
fetch未使用await且未处理错误:无法确认请求是否成功完成- 按钮
onClick提前触发刷新:网络延迟时,评论还没提交完成就刷新页面 - 未设置请求头:部分生产环境服务器需要明确指定
Content-Type - 错误提示不明确:用户无法知晓具体的验证失败原因
修复后的表单组件代码:
import { useForm } from "react-hook-form"; function Form({ _id }) { const { register, handleSubmit, formState: { errors }, reset, } = useForm(); const onSubmit = async (data) => { try { const response = await fetch('/api/CreateComment', { method: "POST", headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ ...data, _id }) }) const result = await response.json() if (result.success) { reset() // 提交成功后清空表单 setTimeout(() => { window.location.reload() }, 3000); } else { alert(result.message) } } catch (error) { console.error('提交评论失败:', error) alert('评论提交失败,请稍后重试') } } return ( <form id='my-form' onSubmit={handleSubmit(onSubmit)}> <div> <label htmlFor="name">你的名字</label> <input {...register('name', { required: "请填写名字", minLength: { value: 3, message: "名字至少3个字符" } })} type="text" id="name" /> {errors.name && <span style={{color: 'red'}}>{errors.name.message}</span>} <div> <label htmlFor="comment">你的评论</label> <textarea {...register('comment', { required: "请填写评论", minLength: { value: 5, message: "评论至少5个字符" } })} id="comment" rows="4" ></textarea> {errors.comment && <span style={{color: 'red'}}>{errors.comment.message}</span>} </div> <div> <button type="submit"> 发布评论 </button> </div> </div> </form> ); } export default Form;
额外排查点
- 生产环境环境变量:确认
SANITY_AUTH_TOKEN、SANITY_PROJECT_ID等变量已在部署平台(如Vercel、Netlify)正确配置 - Sanity权限:检查
SANITY_AUTH_TOKEN是否拥有创建comment文档的权限 - CORS设置:如果Sanity与网站域名不同,需在Sanity控制台配置正确的CORS origins
内容的提问来源于stack exchange,提问作者MIAN G
相关产品推荐
相关产品推荐

