最后说说Vue2 SSR 的 Cookies 问题

2020-06-13 10:36:38易采站长站整理


import { createApp } from './app'
import { api } from '~api'
export default function(context) {
return new Promise((resolve, reject) => {
const s = Date.now()
const { app, router, store } = createApp()
const url = context.url
const fullPath = router.resolve(url).route.fullPath
if (fullPath !== url) {
reject({ url: fullPath })
}
router.push(url)
router.onReady(() => {
const matchedComponents = router.getMatchedComponents()
if (!matchedComponents.length) {
reject({ code: 404 })
}
// 注意这里, 在步骤2中, context里已经带有cookies了
// 创建一个新的api实例, 并把cookies传进去
// 同时注入store和根状态中
// 注入 store 中, 可以方便在组件中用
// 注入 根状态中, 可以方便在 vuex 的 actions 中用
store.$api = store.state.$api = api(context.cookies)
Promise.all(
matchedComponents.map(
({ asyncData }) =>
asyncData &&
asyncData({
store,
route: router.currentRoute,
cookies: context.cookies,
isServer: true,
isClient: false
})
)
)
.then(() => {
console.log(`data pre-fetch: ${Date.now() - s}ms`)
context.state = store.state
context.isProd = process.env.NODE_ENV === 'production'
resolve(app)
})
.catch(reject)
}, reject)
})
}

示例文件: src/entry-server.js

4. 修改客户端入口文件


import api from '~api'
// 前后代码略
const { app, router, store } = createApp()

if (window.__INITIAL_STATE__) {
store.replaceState(window.__INITIAL_STATE__)
// 客户端就没必要用工厂函数了, 用也可以, 但是需注意, api里的属性必须和服务端的保持一致
store.$api = store.state.$api = api
}
// 前后代码略

示例文件: src/entry-client.js

5. 在 vuex 的 actions 中使用


const actions = {
async ['getArticleList'](
{
commit,
state,
rootState: { $api } // 这里就是前面注入的api
},
config
) {
const {
data: { data, code }
} = await $api.get('frontend/article/list', { ...config, cache: true })
if (data && code === 200) {
commit('receiveArticleList', {
...config,
...data
})
}
}
}

示例文件: src/store/modules/frontend-article.js