>웹 프론트엔드 >JS 튜토리얼 >Vue SSR의 쿠키 관련 문제 분석

Vue SSR의 쿠키 관련 문제 분석

不言
不言원래의
2018-06-30 17:09:491784검색

이 글은 주로 Vue SSR의 쿠키 문제를 소개하고 있습니다. 내용이 꽤 괜찮아서 참고용으로 올려드리겠습니다.

웹사이트에 여러 사용자가 참여하면 쿠키에서 벗어나기가 어렵습니다. Vue SSR의 쿠키는 정말 큰 문제입니다. SSR을 플레이하는 초기부터 지금까지 저는 쿠키를 삽입하는 초기 단계부터 3가지 솔루션을 생각해 냈습니다. 상태로 쿠키를 전역으로 주입하고 이제 구성 요소의 asyncData 메서드에 쿠키를 주입합니다.

Vue의 업그레이드로 첫 번째 솔루션은 더 이상 적용 가능하지 않으며 두 번째 솔루션도 사용할 수 있습니다. 많은 제한이 있으므로 세 번째 옵션을 생각했고 구체적인 구현 방법에 대해 이야기해 보겠습니다.

첫 번째 옵션

첫 번째 옵션은 더 이상 적용되지 않으므로 여기서 자세히 설명하지 않겠습니다

두 가지 옵션

아이디어: ssr의 컨텍스트에 쿠키를 삽입한 다음 API를 요청할 때 이를 읽은 다음 이를 axios의 헤더에 추가합니다.

1 먼저 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)
})

그 후 Vue는 global.__VUE_SSR_CONTEXT__

2에 컨텍스트를 추가하고 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
 },
}

이 작업을 수행할 수 있는 이유는 무엇입니까?

기본적으로 Vue는 렌더링할 때마다 번들을 렌더러는 새로운 V8 컨텍스트를 생성하고 전체 번들을 다시 실행합니다. 애플리케이션 코드는 서버 프로세스와 격리되어 있으므로 액세스되는 각 사용자 컨텍스트는 독립적이며 서로 영향을 미치지 않습니다.

그러나 Vue@2.3.0부터 createBundleRenderer 메소드의 옵션에 runInNewContext 옵션이 추가됩니다. runInNewContext : false, 번들 코드는 서버 프로세스와 동일한 전역 컨텍스트에서 실행되므로 더 이상 전역에 쿠키를 넣을 수 없습니다. 이렇게 하면 모든 사용자가 동일한 쿠키를 공유하게 되기 때문입니다.

지금 이렇게 하면 어떨까요?

그럼 계속해서 runInNewContext를 true로 설정해 보겠습니다. 물론 가능하지만 컨텍스트를 다시 생성하고 전체 번들을 실행하는 것은 여전히 ​​비용이 많이 듭니다. 특히 애플리케이션이 큰 경우에는 더욱 그렇습니다. 블로그 예를 들어 예전에는 라우팅 컴포넌트 5개만 렌더링했는데, loadtest의 rps는 50 정도였습니다. 그런데 SSR에 백그라운드의 라우팅 컴포넌트 12개를 추가하고 나니 rps가 바로 한 자릿수로 떨어졌네요...

그래서 지금은 세 번째 옵션이 나타납니다

세 번째 옵션


아이디어: 쿠키를 구성 요소의 asyncData 메서드에 매개 변수로 삽입한 다음 매개 변수를 전달하여 쿠키를 API에 전달합니다. 하지만 이것이 제가 생각하는 더 좋은 방법입니다.

1단계:

여전히 server.js에서 컨텍스트에 쿠키를 삽입합니다

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)
})

2단계:

entry-server.js에서 쿠키를 전달합니다. 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)

3단계:

구성요소에서 쿠키를 Vuex 액션에 매개변수로 전달합니다

export default {
 name: 'frontend-index',
 async asyncData({store, route, cookies}, config = { page: 1}) {
  config.cookies = cookies
  await store.dispatch('frontend/article/getArticleList', config)
 }
 // .....
}

4단계:

Vuex에서 쿠키는 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
}

여기서 상태는 함수 반환 값으로 초기화되어야 한다는 점에 유의해야 합니다. 그렇지 않으면 상태는 모든 사용자가 공유하게 됩니다.

5단계:

API에서 쿠키를 수신하고 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
   }
  })
 },
}

네 번째 구성표

1단계:

여전히 Server.js에서 컨텍스트에 쿠키를 삽입합니다.

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)
})

2단계:

엔트리 서버에서. Node.js에서 쿠키를 api.setCookies 메소드에 매개변수로 전달합니다. 더 이상 4단계는 필요 없습니다. API 호출을 직접 소개하세요

Axios를 다시 패키징하지 않은 경우 다섯 번째 단계를 생략하고 네 번째 부분에서 쿠키를 Axios에 직접 전달할 수도 있습니다

Plan 2 구체적인 예: https:/ /github.com/lincenying/mmf-blog-vue2-ssr

Plan 3 구체적인 예: https://github.com/lincenying/mmf-blog-vue2-pwa-ssr

옵션 4의 구체적인 예: https: //github.com/lincenying/mmf-blog-vue2-pwa-ssr

결론적으로 프로젝트가 크지 않다면 옵션 2를 사용하면 됩니다. 프로젝트의 페이지가 많고 크기가 큽니다. 일부 페이지는 동일합니다. 모든 사용자에 대해 옵션 3을 고려할 수 있으며 더 나은 방법이 있으면 토론을 환영합니다

Vue SSR에는 SEO가 필요하며 각 사용자가 보는 콘텐츠는 캐싱과 함께 일관되며 매우 좋은 경험이 될 것입니다.. .

위 내용은 이 글의 전체 내용입니다. 모든 분들의 학습에 도움이 되었으면 좋겠습니다. 더 많은 관련 내용은 PHP 중국어 홈페이지를 주목해주세요!

관련 추천:

Vue2 SSR 캐싱 Api 데이터 방법에 대해

Vue2.0 프로젝트 라우팅 점프 구현 방법 소개


위 내용은 Vue SSR의 쿠키 관련 문제 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.