Heim > Artikel > Web-Frontend > Analyse von Cookies-Problemen bei Vue SSR
Dieser Artikel stellt hauptsächlich das Cookie-Problem von Vue SSR vor. Der Inhalt ist ziemlich gut. Ich werde ihn jetzt mit Ihnen teilen und als Referenz verwenden.
Sobald eine Website mehrere Benutzer umfasst, ist es schwierig, den Cookies von Vue SSR zu entkommen. Von Beginn an bis heute habe ich mir insgesamt 3 ausgedacht Optionen, vom frühesten Einfügen von Cookies in den Status über das Einfügen von Cookies in den globalen Bereich bis hin zum aktuellen Einfügen von Cookies in die asyncData-Methode der Komponente.
Mit dem Upgrade von Vue war die erste Option nicht mehr vorhanden Anwendbar. Die zweite Option hat auch viele Einschränkungen, daher habe ich über die spezifische Implementierungsmethode nachgedacht:
Die erste Option
Die zweite Lösung
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) })
, Vue fügt Kontext zu global.__VUE_SSR_CONTEXT__ hinzu
2, Cookies in api.js lesen
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 }, }Warum ist das so? möglich?
Standardmäßig erstellt Vue für jedes Rendern einen neuen V8-Kontext und führt das gesamte Bundle erneut aus. Der Anwendungscode ist vom Serverprozess isoliert, sodass jeder Benutzerkontext, auf den zugegriffen wird, unabhängig ist und sich nicht gegenseitig beeinflusst.
Aber ab Vue@2.3.0 wird runInNewContext in den Optionen der Methode „createBundleRenderer“ hinzugefügt , verwenden Sie runInNewContext: false, der Bundle-Code wird im gleichen globalen Kontext wie der Serverprozess ausgeführt, sodass wir keine globalen Cookies mehr platzieren können, da dies dazu führt, dass alle Benutzer dieselben Cookies verwenden.
Warum machen Sie das nicht jetzt?
Dann setzen wir runInNewContext weiterhin auf true, nicht wahr? Natürlich ist es möglich, aber den Kontext neu zu erstellen und das gesamte Bundle auszuführen ist immer noch ziemlich teuer, insbesondere wenn die Anwendung sehr groß ist.
In meinem eigenen Blog habe ich zuvor nur 5 Routing-Komponenten gerendert und die RPS des Lasttests betrug etwa 50, aber später habe ich 12 Routing-Komponenten hinzugefügt Komponenten im Hintergrund. Nach dem Hinzufügen von SSR fielen die RPS direkt auf einstellige Werte...
Also erschien die dritte Lösung
Die dritte Lösung
Idee: Cookies als Parameter in die asyncData-Methode der Komponente einfügen und die Cookies dann durch Übergeben von Parametern an die API übergeben. Ich muss sagen, dass diese Methode sehr mühsam ist, aber das ist das Beste, was ich mir vorstellen kann von. Methode
Schritt 1:
Immer noch in server.js, Cookies in den Kontext einfügen
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) })
Schritt 2:
In enter-server.js Cookies als Parameter an die asyncData-Methode übergeben
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)
Schritt 3:
In Geben Sie in der Komponente Cookies als Parameter für Vuex-Aktionen an
export default { name: 'frontend-index', async asyncData({store, route, cookies}, config = { page: 1}) { config.cookies = cookies await store.dispatch('frontend/article/getArticleList', config) } // ..... }
Schritt 4:
Cookies als Parameter in Vuex für die API einfügen
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 }
Hier müssen Sie darauf achten, dass der Status mit dem Rückgabewert der Funktion initialisiert werden muss, sonst werden alle Benutzer den Status teilen
Schritt 5:
Empfangen Sie Cookies in der API und fügen Sie sie zu den Headern von Axios hinzu
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 } }) }, }Die vierte Option
Schritt 1:
Immer noch in server.js, Cookies in den Kontext einfügen
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) })
Schritt 2:
In enter-server.js, übergeben Sie Cookies als Parameter an die Methode api.setCookies, gefolgt von
api.setCookies(context.cookies) // 这一句 Promise.all(matchedComponents.map(({asyncData}) => asyncData && asyncData({ store, route: router.currentRoute, cookies: context.cookies, isServer: true, isClient: false }))).then(() => { // ... }
Schritt 3:
API.js neu schreiben
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 }) } }
Schritt 4:
Kein Schritt 4 mehr, einfach den API-Aufruf direkt einführen
Wenn Sie Axios nicht neu gepackt haben, können Sie den fünften Schritt auch weglassen und die Cookies im vierten Schritt direkt an Axios übergeben
Option 2 ist spezifisch Beispiel: https://github.com/lincenying/ mmf-blog-vue2-ssr
Option 3 Spezifisches Beispiel: https://github.com/lincenying/mmf-blog-vue2-pwa-ssr
Spezifisches Beispiel für Option 4: https ://github.com/lincenying/mmf-blog-vue2-pwa-ssr
Um es zusammenzufassen: Wenn Ihr Projekt nicht groß ist, verwenden Sie einfach Option 2. Das Projekt hat viele Seiten und die meisten davon Die Seiten sind für jeden Benutzer gleich. Sie können Option 3 in Betracht ziehen. Wenn Sie bessere Methoden haben, können Sie diese gerne besprechen.
Vue SSR erfordert SEO, und jeder Benutzer sieht einen konsistenten Inhalt. Es wird eine sehr gute Erfahrung sein...
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, er wird für das Lernen aller hilfreich sein. Bitte beachten Sie die PHP-Chinesisch-Website Inhalt!
Verwandte Empfehlungen:
Über die Methode des Vue2 SSR-Caching von API-DatenDas Vue2.0-Projekt implementiert die Routing-Jump-Methode EinführungDas obige ist der detaillierte Inhalt vonAnalyse von Cookies-Problemen bei Vue SSR. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!