cookies 都是存在浏览器端, 而 ssr 时, 是在服务器请求的接口, 默认情况肯定带不了浏览器的 cookies, 然而一些登录后的页面数据又必须要 cookies, 这可怎么办
1. 通过 express 取得 cookies
在 server.js 上引入 cookies 解析中间件
const cookieParser = require('cookie-parser')
并且在路由前面 use
app.use(cookieParser())
2. 将 cookies 注入 render 的上下文中
app.get('*', (req, res) => {
// 其他代码省略
const context = {
url: req.url,
cookies: req.cookies
}
const renderStream = renderer.renderToStream(context)
// 其他代码省略
})
3. 将 cookies 注入 vuex 的 store 中
在server-entry.js
文件中, 将 cookies 注入到 store 中
export default context => {
// 其他代码省略
if (context.cookies) {
store.state.cookies = context.cookies
}
// 其他代码省略
}
这样就可以在组件中取到 cookies 了.
4. 封装请求
这里以 axios 为例, 将 cookies 加载封装函数的参数中:
注意: 这里的封装, 建议将浏览器用的和 node 用的分开
import axios from 'axios'
const parseCookie = cookies => {
let cookie = ''
Object.keys(cookies).forEach(item => {
cookie+= item + '=' + cookies[item] + '; '
})
return cookie
}
export default {
get(url, params, cookies = {}) {
const cookie = parseCookie(cookies)
return axios({
method: 'get',
url,
params,
headers: {
'X-Requested-With': 'XMLHttpRequest',
cookie
}
})
}
}
5. 发起带 cookies 参数的请求
在组件中 dispatch vuex 的 actions:
const fetchInitialData = async (store, config = { page: 1}) => {
await store.dispatch('frontend/article/getList', config)
}
export default {
name: 'frontend-index',
prefetch: fetchInitialData,
// 其他代码省略
}
在 vuex 的 actions 中, 从 store 里读取 cookies, 作为参数传给请求接口的函数
async ['getList']({commit, rootState: {cookies}}, config) {
const { data: { data, code} } = await api.get('/api/article/list', config, cookies)
// 其他代码省略
}
6. 几个注意点
1, cookies的内容中不允许带中文, 不知道从什么版本开始, http-server 的 header 里有中文就直接报错
2, import store from '../store'
这种方式下的 store 是不会带 cookies 的
这样就完成了, 虽然不够优雅, 但也总算是实现了, vue ssr 的文章真是太少了, 找资料太费劲了, 如果有更好的方法, 希望大神能不吝指正
完整源码: https://github.com/lincenying...
完整实例: https://www.mmxiaowu.com/