我以前一直使用Vue来写前端。去年下半年接手了一个基于React + Next.js的项目,于是顺带学习了一下Next.js。由于Next.js的特点,这个项目的前后端是放在一起的。一开始没什么问题,看了半天文档就上手了。
上周我们需要在另一个网页项目中,调用这个项目的后端接口,于是就需要处理跨域请求的问题。但我发现按照网上的方法,跨域问题依然存在。这个问题浪费了我不少时间,好在最后终于找到了原因。记录在这里,免得大家跟我一样踩坑。
为了复现这个问题,我们先来创建一个Next.js项目。执行代码创建代码脚手架:
1 | npx create-next-app test_cors |
使用TypeScript,其他选项选择默认,如下图所示:
命令执行完成以后,会生成一个test_cors
文件夹,在文件夹中创建文件pages/api/test.ts
。内容如下:
1 | import { NextResponse } from 'next/server' |
如下图所示:
然后运行命令npm run dev
。这个后端接口就启动起来了。我们可以使用Postman来进行测试:
接下来,我们来写一段HTML代码,触发跨域问题:
1 |
|
直接双击打开这个html文件,点击页面上的按扭,就会触发跨域报错,如下图所示:
然后,你在网上用关键词搜索next.js 跨域
或者next.js cors
,一般看到的文章都会让你直接在next.config.js
文件中添加响应头,如下图所示:
你按照这些文章中写到方法加了配置,重启服务,然后用Postman来测试,你会发现返回的响应头里面确实已经有这几项了,如下图所示:
但当你使用HTML页面来测试时,跨域的报错还在。
你连续打开Google上面10篇讲Next.js跨域的文章,无论是中文博客还是英文博客,甚至你直接使用ChatGPT来问,他们给你的回复肯定都是上面的这个方法。但是无论你怎么测试,跨域问题还在。
实际上,跨域就是这样配置的。你的配置没有任何问题。问题出现在你的后端代码上,如下图所示:
首先你需要是一个POST请求,你才能执行await req.json()
。而浏览器在判断能不能跨域时,会首先发送一个OPTIONS
请求,如下图所示:
这个请求也会走到你的这段后端代码里面。但由于OPTIONS请求没有Body,于是代码运行到await req.json()
时,就会报错。于是浏览器认为OPTIONS
请求没有返回status 200,因此强行认为你的接口不支持跨域。
那么解决方法也非常简单,提前判断一下请求方法是不是OPTIONS就可以了:
1 | if(req.method === 'OPTIONS') { |
如下图所示:
运行效果如下图所示,跨域成功:
这个问题对于资深前端来说,可能不值一提。但对于后端兼职前端的人,或者第一次接触Next.js的人来说,可能是一个深坑,会浪费很多的时间。
未闻Code Telegram Channel开通了!每天都有各种开发小技巧更新,速来!!