이 글은 주로 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!