最后说说Vue2 SSR 的 Cookies 问题
本来想前面写点什么的,还是算了,直接说思路吧. 从 Vue2.3 版本后,SSR 的 cookies,就变成一个无比麻烦的问题,具体请访问官网文档: https://ssr.vuejs.org/zh/api.html#runinnewcontext 之前也说不少的思路,可是都觉得不怎么好用,虽然都能解决问题,今天再说一种思路 因为 Vue2.3 以后,bundle 代码将与服务器进程在同一个 global 上下文中运行,所以不能再将 cookies 丢到 global 给 api 使用,否则就会出现 cookies 污染 Vue2.3 以后,我们需要为每个请求创建一个新的根 Vue 实例,同样的,router、store 也需要,所以,我们的思路也在此,将封装后的 api 注入到这 3 个实例当中去,保证每个请求的 api 都是独立,那么就剩一个问题,注入到哪个实例里面去!? api 请求用到最多的两个地方就是: 组件和 vuex 的 actions 里,这两个地方都有 store 的影子,注入到 store 中,毫无疑问是最好的 那么下面就来操作下: 1. 修改 api,让 api 文件导出一个工厂函数const parseCookie = cookies => {
let cookie = '' Object.keys(cookies).forEach(item => { cookie += item + '=' + cookies[item] + '; ' }) return cookie } export const api = cookies => { 把 cookies 当参数传进工厂函数,给 axios 使用 示例文件1: src/api/index-server.js 示例文件2: src/api/index-client.js 2. 修改 server.js 文件,将 cookies 注入 renderer 的 上下文中 {
if (err) {
return handleError(err)
}
res.end(html)
if (!isProd) {
console.log(`whole request: ${Date.now() - s}ms`)
}
})
// 前后代码略
示例文件: server.js 3. 修改服务端入口文件 {
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. 修改客户端入口文件if (window.INITIAL_STATE) {
store.replaceState(window.INITIAL_STATE) // 客户端就没必要用工厂函数了,用也可以,但是需注意,api里的属性必须和服务端的保持一致 store.$api = store.state.$api = api } // 前后代码略 示例文件: src/entry-client.js 5. 在 vuex 的 actions 中使用示例文件: src/store/modules/frontend-article.js 6. 在组件中使用示例文件: src/components/frontend-comment.vue 至此,全文结束,完整代码,请参考: https://github.com/lincenying/mmf-blog-vue2-pwa-ssr 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |