Cet article présente principalement le problème des cookies de Vue SSR. Le contenu est assez bon, je vais le partager avec vous maintenant et le donner comme référence.
Une fois qu'un site Web implique plusieurs utilisateurs, il est difficile d'échapper aux cookies. Les cookies de Vue SSR sont vraiment un gros problème. Depuis le début de SSR jusqu'à maintenant, j'en ai trouvé un total de 3. options, depuis la première injection de cookies dans l'état, jusqu'à l'injection de cookies dans global, jusqu'à l'injection actuelle de cookies dans la méthode asyncData du composant.
Avec la mise à niveau de Vue, la première option a été Elle n'est plus applicable. La deuxième option présente également de nombreuses limites, j'ai donc pensé à la troisième option. Parlons de la méthode de mise en œuvre spécifique :
La première option
. La première solution n'est plus applicable et ne sera pas abordée en détail ici
La deuxième solution
Idée : Injecter des cookies dans un contexte ssr, puis lire lors de la demande de l'API, puis ajoutez-la à l'en-tête d'axios
1. Ajoutez d'abord les cookies au contexte dans server.js
const context = { title: 'M.M.F 小屋', description: 'M.M.F 小屋', url: req.url, cookies: req.cookies } renderer.renderToString(context, (err, html) => { if (err) { return errorHandler(err) } res.end(html) })
Après cela, Vue ajoutera du contexte à global.__VUE_SSR_CONTEXT__
2, lisez les cookies dans api.js
import axios from 'axios' import qs from 'qs' import md5 from 'md5' import config from './config-server' const SSR = global.__VUE_SSR_CONTEXT__ const cookies = SSR.cookies || {} const parseCookie = cookies => { let cookie = '' Object.keys(cookies).forEach(item => { cookie+= item + '=' + cookies[item] + '; ' }) return cookie } export default { async post(url, data) { const cookie = parseCookie(cookies) const res = await axios({ method: 'post', url: config.api + url, data: qs.stringify(data), timeout: config.timeout, headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', cookie } }) return res }, }
Pourquoi cela peut-il être fait ?
Par défaut, Vue pour chaque rendu, le moteur de rendu du bundle créera un nouveau contexte V8 et le réexécutera dans son intégralité. Le code de l'application est isolé du processus serveur, donc chaque contexte utilisateur accédé est indépendant et ne s'affectera pas les uns les autres.
Mais à partir de Vue@2.3.0, runInNewContext est ajouté dans les options de l'option de méthode createBundleRenderer , utilisez runInNewContext : false, le code du bundle s'exécutera dans le même contexte global que le processus serveur, nous ne pouvons donc plus mettre de cookies en global, car cela amènera tous les utilisateurs à partager les mêmes cookies.
Pourquoi ne pas faire cela maintenant ?
Ensuite, continuons à définir runInNewContext sur true, n'est-ce pas bien sûr possible, mais recréant le contexte et exécutant l'intégralité du bundle ? est encore assez cher, surtout lorsque l'application est très volumineuse
En prenant mon propre blog comme exemple, je n'ai rendu que 5 composants de routage auparavant, et le rps du test de charge était d'environ 50, mais plus tard j'ai ajouté 12 composants de routage. composants en arrière-plan. Après avoir ajouté SSR, le rps est tombé directement à un chiffre...
La troisième solution est donc apparue
La troisième solution
Idée : injectez des cookies en tant que paramètres dans la méthode asyncData du composant, puis transmettez les cookies à l'API en passant des paramètres. Je dois dire que cette méthode est très gênante, mais c'est la meilleure chose à laquelle je puisse penser. de.Méthode
Étape 1 :
Toujours dans server.js, injecter des cookies dans le contexte
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) })
Étape 2 :
Dans Entry-server.js, transmettez les cookies en tant que paramètres à la méthode asyncData
Promise.all(matchedComponents.map(({asyncData}) => asyncData && asyncData({ store, route: router.currentRoute, cookies: context.cookies, isServer: true, isClient: false }))).then(() => { context.state = store.state context.isProd = process.env.NODE_ENV === 'production' resolve(app) }).catch(reject)
Étape 3 :
Dans le composant, transmettez les cookies comme paramètres aux actions Vuex
export default { name: 'frontend-index', async asyncData({store, route, cookies}, config = { page: 1}) { config.cookies = cookies await store.dispatch('frontend/article/getArticleList', config) } // ..... }
Étape 4 :
Dans Vuex Pass, les cookies comme paramètres à l'API
import api from '~api' const state = () => ({ lists: { data: [], hasNext: 0, page: 1, path: '' }, }) const actions = { async ['getArticleList']({commit, state}, config) { // vuex 作为临时缓存 if (state.lists.data.length > 0 && config.path === state.lists.path && config.page === 1) { return } let cookies if (config.cookies) { cookies = config.cookies delete config.cookies } const { data: { data, code} } = await api.get('frontend/article/list', {...config, cache: true}, cookies) if (data && code === 200) { commit('receiveArticleList', { ...config, ...data, }) } }, } const mutations = { ['receiveArticleList'](state, {list, hasNext, hasPrev, page, path}) { if (page === 1) { list = [].concat(list) } else { list = state.lists.data.concat(list) } state.lists = { data: list, hasNext, hasPrev, page, path } }, } const getters = { } export default { namespaced: true, state, actions, mutations, getters }
Assurez-vous de noter ici que l'état doit être initialisé avec la valeur de retour de la fonction, sinon tous les utilisateurs passeront à l'état partagé
Étape 5 :
Recevez les cookies dans l'API et ajoutez-les aux en-têtes d'axios
import axios from 'axios' import qs from 'qs' import config from './config-server' const parseCookie = cookies => { let cookie = '' Object.keys(cookies).forEach(item => { cookie+= item + '=' + cookies[item] + '; ' }) return cookie } export default { get(url, data, cookies = {}) { const cookie = parseCookie(cookies) return axios({ method: 'get', url: config.api + url, data: qs.stringify(data), timeout: config.timeout, headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', cookie } }) }, }
La quatrième option
Étape 1 :
Toujours dans server.js, injecter des cookies dans le contexte
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) })
Étape 2 :
Dans Entry-server.js, transmettez les cookies en tant que paramètres à la méthode api.setCookies suivi de
api.setCookies(context.cookies) // 这一句 Promise.all(matchedComponents.map(({asyncData}) => asyncData && asyncData({ store, route: router.currentRoute, cookies: context.cookies, isServer: true, isClient: false }))).then(() => { // ... }
import axios from 'axios' import qs from 'qs' import config from './config-server' const parseCookie = cookies => { let cookie = '' Object.keys(cookies).forEach(item => { cookie+= item + '=' + cookies[item] + '; ' }) return cookie } export default { api: null, cookies: {}, setCookies(value) { value = value || {} this.cookies = value this.api = axios.create({ baseURL: config.api, headers: { 'X-Requested-With': 'XMLHttpRequest', cookie: parseCookie(value) }, timeout: config.timeout, }) }, post(url, data) { if (!this.api) this.setCookies() return this.api({ method: 'post', url, data: qs.stringify(data), headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', } }).then(res => { return res }) }, get(url, params) { if (!this.api) this.setCookies() return this.api({ method: 'get', url, params, }).then(res => { return res }) } }
Étape 4 :Il n'y a pas d'étape 4, introduisez simplement l'appel api directementSi vous n'avez pas reconditionné axios, vous pouvez également omettre la cinquième étape et passer directement à la quatrième étape Donnez simplement les cookies à axiosExemple spécifique de l'option 2 : https://github.com/lincenying/mmf-blog-vue2-ssrExemple spécifique de l'option 3 : https:// github.com/lincenying/mmf-blog -vue2-pwa-ssrOption 4 Exemple spécifique : https://github.com/lincenying/mmf-blog-vue2-pwa-ssrPour résumer, si votre projet est pas grand, vous devriez simplement utiliser l'option 2. Le projet comporte de nombreuses pages, et la plupart des pages sont les mêmes pour chaque utilisateur. Vous pouvez envisager l'option 3. Si vous avez une meilleure méthode, veuillez en discuter
Vue SSR nécessite du SEO, et le contenu vu par chaque utilisateur est cohérent Avec la mise en cache, ce sera une très bonne expérience...
C'est tout pour cet article. L'intégralité du contenu, je l'espère. sera utile à l'étude de chacun. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois !
Recommandations associées :
À propos de la méthode de mise en cache des données API de Vue2 SSRLe projet vue2.0 implémente la méthode de saut de routage présentationCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!