最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

最后說說Vue2 SSR 的 Cookies 問題

來源:懂視網 責編:小采 時間:2020-11-27 22:14:06
文檔

最后說說Vue2 SSR 的 Cookies 問題

最后說說Vue2 SSR 的 Cookies 問題:本來想前面寫點什么的, 還是算了, 直接說思路吧. 從 Vue2.3 版本后, SSR 的 cookies, 就變成一個無比麻煩的問題, 具體請訪問官網文檔: https://ssr.vuejs.org/zh/api.html#runinnewcontext 之前也說不少的思路, 可是都覺得不怎么好用, 雖然都能
推薦度:
導讀最后說說Vue2 SSR 的 Cookies 問題:本來想前面寫點什么的, 還是算了, 直接說思路吧. 從 Vue2.3 版本后, SSR 的 cookies, 就變成一個無比麻煩的問題, 具體請訪問官網文檔: https://ssr.vuejs.org/zh/api.html#runinnewcontext 之前也說不少的思路, 可是都覺得不怎么好用, 雖然都能

本來想前面寫點什么的, 還是算了, 直接說思路吧.

從 Vue2.3 版本后, SSR 的 cookies, 就變成一個無比麻煩的問題, 具體請訪問官網文檔: https://ssr.vuejs.org/zh/api.html#runinnewcontext

之前也說不少的思路, 可是都覺得不怎么好用, 雖然都能解決問題, 今天再說一種思路

因為 Vue2.3 以后, bundle 代碼將與服務器進程在同一個 global 上下文中運行, 所以不能再將 cookies 丟到 global 給 api 使用, 否則就會出現 cookies 污染

Vue2.3 以后, 我們需要為每個請求創(chuàng)建一個新的根 Vue 實例, 同樣的, router、store 也需要, 所以, 我們的思路也在此, 將封裝后的 api 注入到這 3 個實例當中去, 保證每個請求的 api 都是獨立, 那么就剩一個問題, 注入到哪個實例里面去!?

api 請求用到最多的兩個地方就是: 組件和 vuex 的 actions 里, 這兩個地方都有 store 的影子, 所以, 注入到 store 中, 毫無疑問是最好的

那么下面就來操作下:

1. 修改 api, 讓 api 文件導出一個工廠函數

import axios from 'axios'
import qs from 'qs'
import md5 from 'md5'
import config from './config-server'

const parseCookie = cookies => {
 let cookie = ''
 Object.keys(cookies).forEach(item => {
 cookie += item + '=' + cookies[item] + '; '
 })
 return cookie
}

export const api = cookies => {
 return {
 api: axios.create({
 baseURL: config.api,
 headers: {
 'X-Requested-With': 'XMLHttpRequest',
 cookie: parseCookie(cookies)
 },
 timeout: config.timeout
 }),
 post(url, data) {
 return this.api({
 method: 'post',
 url,
 data: qs.stringify(data),
 headers: {
 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
 }
 })
 },
 async get(url, params) {
 return this.api({
 method: 'get',
 url,
 params
 })
 }
 }
}

把 cookies 當參數傳進工廠函數, 給 axios 使用

示例文件1: src/api/index-server.js

示例文件2: src/api/index-client.js

2. 修改 server.js 文件, 將 cookies 注入 renderer 的 上下文中

// 前后代碼略
 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)
 if (!isProd) {
 console.log(`whole request: ${Date.now() - s}ms`)
 }
 })
// 前后代碼略

示例文件: server.js

3. 修改服務端入口文件

import { createApp } from './app'
import { api } from '~api'
export default function(context) {
 return new Promise((resolve, reject) => {
 const s = Date.now()
 const { app, router, store } = createApp()
 const url = context.url
 const fullPath = router.resolve(url).route.fullPath
 if (fullPath !== url) {
 reject({ url: fullPath })
 }
 router.push(url)
 router.onReady(() => {
 const matchedComponents = router.getMatchedComponents()
 if (!matchedComponents.length) {
 reject({ code: 404 })
 }
 // 注意這里, 在步驟2中, context里已經帶有cookies了
 // 創(chuàng)建一個新的api實例, 并把cookies傳進去
 // 同時注入store和根狀態(tài)中
 // 注入 store 中, 可以方便在組件中用
 // 注入 根狀態(tài)中, 可以方便在 vuex 的 actions 中用
 store.$api = store.state.$api = api(context.cookies)
 Promise.all(
 matchedComponents.map(
 ({ asyncData }) =>
 asyncData &&
 asyncData({
 store,
 route: router.currentRoute,
 cookies: context.cookies,
 isServer: true,
 isClient: false
 })
 )
 )
 .then(() => {
 console.log(`data pre-fetch: ${Date.now() - s}ms`)
 context.state = store.state
 context.isProd = process.env.NODE_ENV === 'production'
 resolve(app)
 })
 .catch(reject)
 }, reject)
 })
}

示例文件: src/entry-server.js

4. 修改客戶端入口文件

import api from '~api'
// 前后代碼略
const { app, router, store } = createApp()

if (window.__INITIAL_STATE__) {
 store.replaceState(window.__INITIAL_STATE__)
 // 客戶端就沒必要用工廠函數了, 用也可以, 但是需注意, api里的屬性必須和服務端的保持一致
 store.$api = store.state.$api = api
}
// 前后代碼略

示例文件: src/entry-client.js

5. 在 vuex 的 actions 中使用

const actions = {
 async ['getArticleList'](
 {
 commit,
 state,
 rootState: { $api } // 這里就是前面注入的api
 },
 config
 ) {
 const {
 data: { data, code }
 } = await $api.get('frontend/article/list', { ...config, cache: true })
 if (data && code === 200) {
 commit('receiveArticleList', {
 ...config,
 ...data
 })
 }
 }
}

示例文件: src/store/modules/frontend-article.js

6. 在組件中使用

methods: {
 async recover(id) {
 const {
 data: { code, message }
 } = await this.$store.$api.get('frontend/comment/recover', { id })
 if (code === 200) {
 this.$store.commit('global/comment/recoverComment', id)
 }
 }
}

示例文件: src/components/frontend-comment.vue

至此, 全文結束, 完整代碼, 請參考: https://github.com/lincenying/mmf-blog-vue2-pwa-ssr

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

最后說說Vue2 SSR 的 Cookies 問題

最后說說Vue2 SSR 的 Cookies 問題:本來想前面寫點什么的, 還是算了, 直接說思路吧. 從 Vue2.3 版本后, SSR 的 cookies, 就變成一個無比麻煩的問題, 具體請訪問官網文檔: https://ssr.vuejs.org/zh/api.html#runinnewcontext 之前也說不少的思路, 可是都覺得不怎么好用, 雖然都能
推薦度:
標簽: ssr 問題 的問題
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top