nuxt3框架dev环境启动无法重定向到外部链接

问题描述

应用场景:用户打开网页时,需要检查登录状态,若未登录则需要跳转到 sso 登录页面进行登录,sso 登录页并不在项目中,属于第三方系统。

当前页面:http://localhost:3000/

跳转目标:http://sso.example.com/login

问题:在 dev 环境下,应用启动后,页面会自动跳转到 sso 登录页面,但实际上并没有跳转,而是显示了如下错误信息:

nuxt3框架dev环境启动无法重定向到外部链接

原因分析

由于使用了 vite 作为构建工具,nuxt3 项目启动时,服务端会以较快的速度启动,此时访问主页会看到 nuxt 的启动页面,但由于 SSR 框架的特性,vue 组件并没有完全编译完成,前端就会一直轮询等待服务端编译完成并返回 html,直到服务端返回特地的成功状态码时,才会重新刷新页面。而检查的过程是用 fetch api 实现的。

此时如果服务端返回了 302 重定向,fetch api 会自动跟随重定向到新的地址,但由于是外部域名,对于当前环境来说是跨域的,在外部域名没有配置相应跨域头是,请求就会报跨域错误,而这个跨域错误会导致 fetch api 报错,框架会认为服务端还没有准备完毕,继续轮询导致循环。

解决方案

解决方案是服务端先返回 200 状态码,让前端程序正确理解服务端已构建完成,等到页面请求时再返回:

nuxt3框架dev环境启动无法重定向到外部链接

实现方法:

从排查结果分析,区分 dev 环境下检测请求和文档请求的区分,可通过请求头 sec-fetch-mode 判断

  • sec-fetch-mode: navigate 文档请求
  • sec-fetch-mode: cors 非文档请求

当获取到请求头是 cors 时,说明前端正在检查,此时不要进入业务逻辑,直接返回 200 即可。

1
2
3
4
5
6
7
export default defineNuxtRouteMiddleware(async (to) => {
// nuxt dev 环境下,第一次渲染时,不能301到外部域名,因为前端使用fetch轮询后端,返回外部域名会使得fetch请求跨域而失败,导致页面死循环
// 服务端渲染时 sec-fetch-mode 应为 document,客户端渲染时,应为 undefined
if (process.dev && useRequestHeader("sec-fetch-mode") === "cors") {
return;
}
});

注意要考虑中间件可能在客户端执行,此时获取到的 header 为 undefined。


nuxt3框架dev环境启动无法重定向到外部链接
https://www.wobushi.top/2024/nuxt3框架dev环境启动无法重定向到外部链接/
作者
Pride Su
发布于
2024年5月27日
许可协议