框架背景:开发框架采用vue,需要更好的SEO,更快的内容到达时间,从浏览器看不到对服务器的请求接口,选用开箱即用的。
问题背景:1. 前后分离,需前端存储token及登录后的用户信息;
2. vuex存储数据,当页面刷新时,数据会丢失;
3. 鉴于第一点,采用localstorage或sessionStorage存储数据,页面刷新,数据不会丢失,BUT,localStorage or sessionStorage 是浏览器的对象,服务端渲染页面时,会提示undefined(毕竟服务器是没有这两个对象的);
解决措施: 采用session (本来采用的是express-session,但此模块为开发环境设计,在生产环境会警告可能内存泄漏,故采用cookie-session)
如下:
1. 在项目根目录下新建server.js:
代码如下:
const {Nuxt, Builder} = require('nuxt');const bodyParser = require('body-parser');const session = require('cookie-session');const app = require('express')();const router = require('express').Router()// 用来封装req.bodyapp.use(bodyParser.json());//session 来创建req.sessionapp.use(session({ secret: 'gjr', resave: false, saveUninitialized: false, cookie: {maxAge: 2*24*60*60*1000}}));// 发起post /api/login 请求完成企业用户登录,并添加该用户信息到req.session.firmUserrouter.post('/api/login', (req, res) => { // 收到express服务请求,进行如下处理 if (req.body.token) { req.session.firmUser = { authStatus:req.body.authStatus, id: req.body.id, loginName: req.body.loginName, token: req.body.token} return res.json({ authStatus:req.body.authStatus, id: req.body.id, loginName: req.body.loginName, token: req.body.token}) } res.status(401).json({message: '401 Bad credentials'})});// 发起post /api/logout 请求注销当前企业用户,并从req.session中移除router.post('/api/logout', (req, res) => { delete req.session.firmUser; res.json({ok: true})});app.use(router);// 我们用这些选项初始化 nuxt.js;const isProd = process.env.NODE_ENV === 'production'let config = require('../nuxt.config')config.dev = !isProd;const nuxt = new Nuxt(config);app.use(nuxt.render)// 生产模式不需要buildif(!isProd) { const builder = new Builder(nuxt) builder.build() .catch((error) => { console.log(error) process.exit(1) })}app.listen(8081, function () { console.log('Server is listening on http://localhost:8081')})
需先安装:
npm install express cookie-session body-parser --save
2. 在store的user.js中:
import axios from 'axios'export default { state: { firmUser: null, clientUser: null, proUser: null }, getters: { firmUser: state => state.firmUser, clientUser: state => state.clientUser, proUser: state => state.proUser }, mutations: { SET_FIRMUSER: (state, user) => { state.firmUser = user; } }, actions: { nuxtServerInit({commit}, {req}) { // 将本地服务端数据发送给浏览器 if (req.session && req.session.firmUser) { commit('SET_FIRMUSER', req.session.firmUser) } }, async firmLogin({commit}, {authStatus, id, loginName, token}) { try { const {data} = await axios.post('/api/login', {authStatus, id, loginName, token}) // 向express服务发起请求 commit('SET_FIRMUSER', data) } catch (error) { if (error.response && error.response.status === 401) { throw new Error('bad error') } throw error } }, async firmLogout({commit}) { await axios.post('/api/logout') commit('SET_FIRMUSER', null) } }}
3. 在login.vue中:
login() { this.$refs.form.validate(valid => { if (valid) { this.$fetch.post('/companyUser/login', this.form).then(res => { // 向后台请求 this.$store.dispatch('firmLogin', res.data).then(() => { // 调用store的方法 this.$router.push('/firm/center'); }); }) } })}
以上,token信息或者用户信息就可以在本地服务及浏览器中共享了,且刷新页面不会丢失。
下一节讲启动服务,以及在服务器上怎么用pm2部署nuxtjs程序。