最后说说Vue2 SSR 的 Cookies 问题

网友投稿 249 2023-02-01


最后说说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 文件导出一个工厂函数

import axios from 'axios'

import qs from 'qs'

import md5 from 'md5'

import config from './config-server'

const parseCookie = cookies => {

let cookie = ''

Object.keys(cookies).forEach(item => {

cookie += item + '=' + cookies[item] + '; '

FBbklLS })

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',

url,

params

})

}

}

}

把 cookies 当参数传进工厂函数, 给 axios 使用

示例文件1: src/api/index-server.js

示例文件2: src/api/index-client.js

2. 修改 server.js 文件, 将 cookies 注入 renderer 的 上下文中

// 前后代码略

const context = {

title: 'M.M.F 小屋',

url: req.url,

cookies: req.cookies

}

renderer.renderToString(context, (err, html) => {

if (err) {

return handleError(err)

}

res.end(html)

if (!isProd) {

console.log(`whole request: ${Date.now() - s}ms`)

}

})

// 前后代码略

示例文件: server.js

3. 修改服务端入口文件

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.__FBbklLSINITIAL_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

6. 在组件中使用

methods: {

async recover(id) {

const {

data: { code, message }

} = await this.$store.$api.get('frontend/comment/recover', { id })

if (code === 200) {

this.$store.commit('global/comment/recoverComment', id)

}

}

}

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

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:连接共享文件夹未响应(电脑打开共享文件未响应)
下一篇:vue axios整合使用全攻略
相关文章

 发表评论

暂时没有评论,来抢沙发吧~