最后说说Vue2 SSR 的 Cookies 问题

前端之家收集整理的这篇文章主要介绍了最后说说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 => {
return {
api: axios.create({
baseURL: config.api,headers: {
'X-Requested-With': 'XMLHttpRequest',cookie: parseCookie(cookies)
},timeout: config.timeout
}),post(url,data) {
return this.api({
method: 'post',url,data: qs.stringify(data),headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
})
},async get(url,params) {
return this.api({
method: 'get',params
})
}
}
}

把 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. 修改客户端入口文件

代码略 const { app,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 中使用

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

6. 在组件中使用

示例文件: src/components/frontend-comment.vue

至此,全文结束,完整代码,请参考: https://github.com/lincenying/mmf-blog-vue2-pwa-ssr

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

原文链接:https://www.f2er.com/vue/32164.html

猜你在找的Vue相关文章