Heim  >  Artikel  >  Web-Frontend  >  Analyse von Cookies-Problemen bei Vue SSR

Analyse von Cookies-Problemen bei Vue SSR

不言
不言Original
2018-06-30 17:09:491718Durchsuche

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 erste Lösung ist nicht mehr anwendbar und wird hier nicht im Detail besprochen

Die zweite Lösung

Idee: Cookies in den SSR-Kontext einfügen und dann lesen Wenn Sie die API anfordern und sie dann an den Header von Axios

1 anhängen, fügen Sie zuerst Cookies zum Kontext in server.js hinzu

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-Daten


Das Vue2.0-Projekt implementiert die Routing-Jump-Methode Einführung


Das 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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn