Nuxt.js服务端渲染刷新页面无法读取Cookie问题求助
核心问题根源
Nuxt.js 是SSR框架,页面刷新时会先在服务端渲染,此时直接用universal-cookie初始化的全局实例无法获取请求头中的Cookie,导致Vuex state里的token为空;而客户端能正常读取Cookie,但服务端渲染后的页面状态与客户端不一致,最终引发页面失效。
具体修复步骤
1. 完善服务端Cookie初始化逻辑
在根Store的actions中添加nuxtServerInit钩子,确保服务端渲染时从请求头读取Cookie并初始化Vuex状态:
// 根store/index.js export const actions = { async nuxtServerInit({ dispatch }, { req }) { await dispatch('auth/extractTokenFromRequest', req); } }
同时修正auth模块中的extractTokenFromRequest方法,适配服务端Cookie读取:
async extractTokenFromRequest ({commit}, req) { if (!req || !req.headers.cookie) return; const serverCookies = new Cookies(req.headers.cookie, { path: '/' }); const token = serverCookies.get('token'); if (token) { // 匹配setToken的payload格式 commit('setToken', { access_token: token }); } }
2. 修正生产环境Cookie配置参数
部署到服务器后,Cookie可能因secure、sameSite等参数缺失导致无法读取,修改setToken和clearAuthKey方法:
mutations: { setToken(state, payload) { state.token = payload.access_token; cookies.set('token', payload.access_token, { path: '/', secure: process.env.NODE_ENV === 'production', // 生产环境启用HTTPS安全Cookie sameSite: 'strict', // 根据业务场景可选'lax' domain: process.env.COOKIE_DOMAIN || undefined, // 填写服务器域名,例如'yourdomain.com' maxAge: 3600 * 24 * 7 // 可选:设置Cookie过期时间(7天) }); }, clearAuthKey(state) { cookies.remove("token", { path: '/', secure: process.env.NODE_ENV === 'production', sameSite: 'strict', domain: process.env.COOKIE_DOMAIN || undefined }); state.token = null; } }
3. 优化isAuthenticated getter
避免在服务端环境直接读取Cookie,优先依赖Vuex state:
getters: { isAuthenticated(state) { // 优先使用state中的token if (state.token && state.token !== '') { return state.token; } // 仅在客户端环境尝试读取Cookie if (process.client) { const clientToken = cookies.get('token'); return clientToken || null; } return null; } }
4. 统一actions中token的获取方式
所有接口请求优先从Vuex state获取token,避免直接调用全局Cookie实例:
async getUser({commit, state}, payload) { try { // 优先取state的token,客户端环境再降级读Cookie const token = state.token || (process.client ? cookies.get('token') : null); if (!token) { await this.$router.push('/auth/login'); return; } let response = await fetch(`${process.env.baseURL}/AuthServices/user`, { method: 'POST', headers: { "authenticated": "Bearer " + token, 'Content-Type': 'application/json;charset=utf-8', }, }).then(res => res.json()); if (response.status) { commit('setUser', response.data[0]); } else { await this.$router.push('/auth/login'); } } catch (e) { await this.$router.push('/auth/login'); } }
其他如getUserNameForChatList等接口请求,均按此逻辑修改token获取方式。
内容的提问来源于stack exchange,提问作者Ayyub Hajiyev
相关产品推荐
相关产品推荐

