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/mmf-blog-vue2-ssr
完整实例: https://www.mmxiaowu.com/

发表评论
dingyiming
回复 @dingyiming: 很厉害
dingyiming
不错,学到了