使用nuxt跟eggjs做的服务端渲染,目前遇到问题了,在about页面刷新,eggjs的中间件拿不到用户的session了,哪位大佬帮看看,不知道是nuxt这边的问题还是eggjs这边的问题
中间件定义
const { Nuxt, Builder } = require("nuxt");
let config = require("../../nuxt.config");
module.exports = (options, app) => {
const nuxtRender = new Nuxt(config);
let isDev = process.env.NODE_ENV !== "production";
if (isDev) {
new Builder(nuxtRender).build();
}
return async function(ctx, next) {
let flag = false;
let routerArr = [];
if (!flag) {
routerArr = app.router.stack.map(el => el.path);
flag = true;
}
if (routerArr.some(el => el === ctx.path)) {
return await next();
}
ctx.status = 200;
ctx.req.session = ctx.session;
const { res, req } = ctx;
return new Promise((resolve, reject) => {
ctx.res.on("close", resolve);
ctx.res.on("finish", resolve);
nuxtRender.render(req, res, promise => {
promise.then(resolve).catch(reject);
});
});
};
};
about页面请求
export default {
asyncData({ params }) {
return axios.get("http://127.0.0.1:7001/api/info").then(res => {
return { info: res.data };
});
}
};
nuxtServerInit定义
export const state = () => ({
user: null
});
export const mutations = {
setUser(state, data) {
state.user = data;
}
};
export const actions = {
nuxtServerInit({ commit }, { req }) {
if (req.session.user) {
console.log("client", req.session.user);
commit("setUser", req.session.user);
}
}
};
有人给看看么???大神求教
wwwww
nuxt 的模型,跟 Koa 其实不好匹配的,它是 req/res 的,你网上找到的那些,都是把 req, res 直接丢给 render,但其实是跳出了 Koa 的洋葱模型,不走中间件的了。具体哪一步的问题,你要自己一步步排查下看看了。
你只给了仓库,没有给复现步骤。
@atian25 我自己做了排查,前面都是对的,就是在about页面直接刷新,eggjs这边的session就丢失了,感觉是nuxt这边的问题。但是nuxt这边能够拿到session,不知道是不是我对session这些理解不到位。。
session
不是本来就在server
中进行存取吗?怎么会它自身的中间件拿不到?还是说你禁止了cookie。
如果你是说,server
渲染vue
页面进行的请求拿session
的事情,你可以先在server中请求入口处把session
挂到ctx.req
对象中,然后可以在nuxtServerInit
或者plugins
的req
参数中获取
@lzq920 默认的 session 是基于 cookie 的,你可以看下网络通信的内容有没有对。另,egg 的 session 是加密的,如果你在 nuxt 里面有操作的话,有可能导致解密失败从而为空。
@7demo 在nuxtServerInit里面是能够正常拿到session的,哪怕页面刷新都能拿到,就后端授权中间件那里session的自定义字段丢了
@atian25 但是session中存的csrfToken都在,就自己定义的user就没了
@lzq920 断点分析下吧
https://github.com/eggjs/egg/issues/3554
刷新的时候是服务端请求,你的 axios 在服务端侧时,要把 cookie 带过去。
PS:想玩转 SSR,先把请求链路和 HTTP 这套搞明白。
export default {
asyncData({ params, req }) {
if(process.server){
Object.keys(req.headers).map((key)=>{
axios.defaults.headers.common[key] = req.headers[key];
});
}
return axios.get("http://127.0.0.1:7001/api/info", { withCredentials: true }).then(res => {
return { info: res.data };
});
}
};
@atian25 嗯,受教了。。。感谢
要学习如何快速定位问题:
- 既然是请求 403 了,说明是 auth 没过
- auth 判断的是 session,session 是基于 cookie 的
- 那就在 middleware 那里打印下 cookie,发现没有
- 说明是前面没有传过来,再去看看为什么没传过来。
就这样,一个个的设立阻断点,是左边的错,还是右边的错,二分查下很快就搞定了。
@atian25 一直陷入了一个误区,就是用户登录了,又设置了withCredentials:true,就会自己把cookie传过去。