Nuxt 3页面刷新后Cookie丢失问题排查求助
可能的原因
Cookie配置参数异常
若问题项目中expires参数设置为过去的时间、非标准格式(比如字符串而非Date对象),或path/domain配置过窄(比如path设为特定路由,刷新后页面不在该路径下),会导致浏览器不再识别或携带Cookie,表现为"被清除"。另外,default函数若在刷新时返回undefined/null,可能会覆盖原有Cookie值。服务端/客户端初始化时序冲突
在Nuxt的服务端渲染场景下,useCookie无法直接获取客户端本地存储的Cookie(服务端仅能拿到请求头中的Cookie)。若此时useState初始化时cookie.value为undefined,后续watch触发会将Cookie设为undefined,直接清除原有Cookie。watch逻辑冗余导致的意外覆盖
代码中watch监听state变化后,同时执行cookie.value = value和state.value = value,后者属于冗余操作(watch触发时state已经是新值),可能引发循环触发或状态混乱。若初始化时state值与Cookie不一致,会直接覆盖Cookie为state的初始值(比如undefined)。浏览器隐私策略拦截
若项目部署在跨域环境,或浏览器开启严格隐私模式(如Safari阻止跨站跟踪),未设置SameSite属性的Cookie可能被自动清除。项目环境版本差异
不同项目若使用了不同版本的Nuxt或相关依赖,useCookie/useState的默认行为可能存在差异,比如新版本中Cookie的生命周期、作用域配置默认值改变,导致Cookie异常。
排查方法
查看浏览器Cookie存储详情
在浏览器开发者工具的「Application」(Chrome)或「Storage」(Firefox)面板中,对比刷新前后目标Cookie的expires、path、domain、SameSite等属性,确认是真的被删除,还是浏览器不再携带。添加日志追踪状态流转
修改useOxyAsyncCookie函数,添加关键节点日志,定位异常触发点:import { watch } from 'vue' import { useCookie, useState } from '#imports' import type { CookieOptions } from '#app/composables/cookie' export const useOxyAsyncCookie = <T>(key: string, options?: CookieOptions) => { const cookie = useCookie(key, options) console.log(`[初始化] Cookie ${key} 值:`, cookie.value) const state = useState<T>(key, () => { const initValue = cookie.value console.log(`[初始化] State ${key} 值:`, initValue) return initValue }) watch(state, (value, oldValue) => { console.log(`[变更] State ${key} 从 ${oldValue} 变为 ${value}`) cookie.value = value console.log(`[变更] Cookie ${key} 被设置为:`, cookie.value) }, { immediate: true }) // 开启immediate查看初始触发情况 // 移除冗余的state.value = value return state }刷新页面后查看控制台日志,确认是否存在将Cookie设为
undefined/null的操作,以及初始化阶段是否正确读取到Cookie值。验证Cookie配置有效性
检查问题项目中useOxyAsyncCookie的调用参数:- 确认
expires是未来时间的Date对象; - 显式设置
path: '/'确保全站可访问; - 添加
SameSite: 'Lax'或'Strict'属性规避隐私拦截; - 确认
domain与当前域名一致(无需特殊配置时可省略)。
- 确认
隔离服务端渲染影响
修改Nuxt配置ssr: false,关闭服务端渲染后测试刷新行为。若问题消失,说明是服务端初始化时未正确获取客户端Cookie,导致state初始值异常覆盖Cookie。对比项目环境差异
检查问题项目与正常项目的Nuxt版本、依赖版本(如@nuxt/kit),以及nuxt.config.ts中的Cookie相关配置,定位版本或配置差异。
内容的提问来源于stack exchange,提问作者Dmytro Afanasiev

