记录一下,今天遇到的NextJS CORS小坑,希望可以帮到有缘人。
NextJS作为全栈框架,可以开发api,那我们早期就可以弄出一个白嫖的api server方法,就是NextJS用来开发API,然后部署到Vercel,这样就不用服务器了。
Vercel本身有限制,API的逻辑不能长时间执行,free plan下是10s,对于多数简单业务,这是够用的,如果你的不够用,建议自建,因为付费后,也只有30s的样子。
对于调用GPT api的服务,要部署到Vercel上,就需要使用stream形式,请参考:https://vercel.com/docs/functions/streaming。
展开一说,很多GPU相关服务都比较耗时,比如画图,比如视频重绘,这种,我此前的做法是使用Serverless GPU来实现,Serverless GPU一般都是异步的,你会获得一个task_id,然后再基于task_id去查询最终的结果,结果会在Serverless平台保存一段时间,然后被删掉,这种,也可以使用Vercel。
后面,有时间可以写一篇使用Serverless GPU的教程,还是有点技巧的。
回到【坑】的话题,为啥标题里有【或】,这是因为我没有自建NextJS去做排除验证。
说说具体的场景,我使用NextJS构建了一个api,使用的是NextJS 14,然后是app目录,我创建了src/app/askai/route.js,然后熟练了写了一个POST方法,然后就提交到Vercel上了。
我使用Postman自测,API通了,然后给到前端同学,前端同事调试,发现报CORS错误,这个很常见,所以一点都不慌,一查文档,便发现了:https://vercel.com/guides/how-to-enable-cors
按照文档操作,修改了next.config.js,然后再部署Vercel,发现没用,我就有点懵,是我英文不好,读漏了关键信息吗?
这种情况也比较常见,因为英文不是母语,看文档时,就容易漏掉一些关键的点,我之前吃过亏,之前跟英国同事共事时,我们在研究twitter api,然后我研究完后,感觉twitter api做不到xxx功能,然后英国同事又进去看了一遍,然后说可以,立即截图出了关键位置,然后我发现,这些关键位置在我眼前晃了几次,我没看见...(梦回高中英文阅读理解)
然后,我开翻译,又看了一遍,感觉没理解错,是不是Vercel有暗坑,必须要设置vercel.json呢?那我也设置上去,然后部署,发现还是不行。
这就奇怪了,我开始怀疑,前端同学的写法有问题,我一翻前端代码,标准的fetch写法,应该没问题,就很奇怪,然后我就上了我的模版代码(go-sea-template,我之前做独立开发技术课的那个模版),然后开CORS,然后请求hello,通了!
那我就放心了,应该是有一些差异点,那么通过排除法必然可以找出问题。
经过反复的修改代码、部署Vercel,终于发现了这个问题,就是route.js中,我只有一个POST方法是不行的,将一个没啥用的GET方法也复制到src/app/askai/route.js中,就正常了,CORS也没问题了,完整的route.js如下:
import { NextResponse } from "next/server";
// get: localhost:3000/api/hello
export async function GET(request) {
// 没啥用的get
return NextResponse.json({
status: 200,
data: {
msg: 'hello get',
},
});
}
// post: localhost:3000/api/hello
export async function POST(req) {
const { key, data } = await req.json()
// 真正的业务逻辑
return NextResponse.json({
status: 200,
data: {
key: key,
data: data
},
});
}
为啥会这样?我也不知道,但其实花时间有可能知道,具体的路径就是:
1.先自建一下NextJS看看是否可以复现。
2.如果复现了,说明答案在NextJS源码里,看源码就好了
3.如果没复现,那么就是未解之谜,因为Vercel那边,你看不了啥
以上。
号外:有几个朋友后台留言要买go-sea-template模版。en...抱歉我不常登录公众号,现在才看见,这说明我们缘分没到,所以不用找我买了,自己动手也是可以实现的,感谢理解。