ssr 从文件导入服务器,Vue SSR, 在服务端请求数据时怎么带 cookies?

该博客详细介绍了如何在Vue 2.0服务端渲染项目中,利用Express的cookie-parser中间件解析Cookies,并将其注入到渲染上下文和Vuex的store中。同时,展示了如何在请求中使用Cookies,确保数据在客户端和服务器之间的一致性。文章还提到了错误处理和性能优化的实践。
摘要由CSDN通过智能技术生成

通过 express 取得 cookies

在 server.js 上引入 cookies 解析中间件

const cookieParser = require('cookie-parser')

并且在路由前面 use

app.use(cookieParser())

部份代码

const fs = require('fs')

const path = require('path')

const LRU = require('lru-cache')

const express = require('express')

const favicon = require('serve-favicon')

const compression = require('compression')

const microcache = require('route-cache')

const resolve = file => path.resolve(__dirname, file)

const { createBundleRenderer } = require('vue-server-renderer')

const isProd = process.env.NODE_ENV === 'production'

const useMicroCache = process.env.MICRO_CACHE !== 'false'

const serverInfo =

`express/${require('express/package.json').version} ` +

`vue-server-renderer/${require('vue-server-renderer/package.json').version}`

const app = express()

// cookie

const cookieParser = require('cookie-parser')

// 并且在路由前面 use

app.use(cookieParser())

将 cookies 注入 render 的上下文中

app.get('*', (req, res) => {

// 其他代码省略

const context = {

url: req.url,

cookies: req.cookies

}

const renderStream = renderer.renderToStream(context)

// 其他代码省略

})

vue 2.0的则改成这样

function render (req, res) {

const s = Date.now()

res.setHeader("Content-Type", "text/html")

// res.setHeader("Server", serverInfo)

// 改header

res.setHeader("Server", 'zibuzhai.com')

res.setHeader("X-Powered-By", 'zibuzhai.com')

const handleError = err => {

if (err.url) {

res.redirect(err.url)

} else if(err.code === 404) {

res.status(404).send('404 | Page Not Found')

} else {

// Render Error Page or Redirect

res.status(500).send('500 | Internal Server Error')

console.error(`error during render : ${req.url}`)

console.error(err.stack)

}

}

const context = {

title: 'title HN 2.0', // default title

keywords: 'keywords HN 2.0', // default keywords

description: 'description HN 2.0', // default description

url: req.url,

cookies: req.cookies

}

renderer.renderToString(context, (err, html) => {

if (err) {

return handleError(err)

}

res.send(html)

if (!isProd) {

console.log(`whole request: ${Date.now() - s}ms`)

}

})

}

app.get('*', isProd ? render : (req, res) => {

readyPromise.then(() => render(req, res))

})

将 cookies 注入 vuex 的 store 中

在server-entry.js文件中, 将 cookies 注入到 store 中

export default context => {

// 其他代码省略

if (context.cookies) {

store.state.cookies = context.cookies

}

// 其他代码省略

}

vue2.0后代码

export default context => {

return new Promise((resolve, reject) => {

const s = isDev && Date.now()

const { app, router, store } = createApp()

if (context.cookies) {

store.state.cookies = context.cookies

}

const { url } = context

const { fullPath } = router.resolve(url).route

if (fullPath !== url) {

return reject({ url: fullPath })

}

// set router's location

router.push(url)

// wait until router has resolved possible async hooks

router.onReady(() => {

const matchedComponents = router.getMatchedComponents()

// no matched routes

if (!matchedComponents.length) {

return reject({ code: 404 })

}

// Call fetchData hooks on components matched by the route.

// A preFetch hook dispatches a store action and returns a Promise,

// which is resolved when the action is complete and store state has been

// updated.

Promise.all(matchedComponents.map(({ asyncData }) => asyncData && asyncData({

store,

route: router.currentRoute,

cookies: context.cookies

}))).then(() => {

isDev && console.log(`data pre-fetch: ${Date.now() - s}ms`)

// After all preFetch hooks are resolved, our store is now

// filled with the state needed to render the app.

// Expose the state on the render context, and let the request handler

// inline the state in the HTML response. This allows the client-side

// store to pick-up the server-side state without having to duplicate

// the initial data fetching on the client.

context.state = store.state

resolve(app)

}).catch(reject)

}, reject)

})

}

这样就可以在组件中取到 cookies 了.

封装请求

import Vue from 'vue'

import axios from 'axios'

import VueAxios from 'vue-axios'

import settings from '../config'

// import store from '../store/index'

// import router from '../router/index'

import createRouter from '../router/index'

import createStore from '../store/index'

import Cookies from 'js-cookie';

Vue.use(VueAxios, axios)

const router = createRouter()

// const store = createStore()

// 动态设置本地和线上接口域名

Vue.axios.defaults.baseURL = settings.host

// 初始化

var configDefault = Vue.axios.defaults.headers

const parseCookie = cookies => {

let cookie = ''

if (cookies) {

Object.keys(cookies).forEach(item => {

cookie+= item + '=' + cookies[item] + '; '

})

}

return cookie

}

export const request = ({type = 'post', url, data = {}, config = {}, globalLoading = false} = {},cookies) => {

let requestCookies = ''

if (JSON.stringify(cookies) && JSON.stringify(cookies) != "{}") {

Object.keys(cookies).forEach(item => {

requestCookies += item + '=' + cookies[item] + '; '

})

}

if (requestCookies) {

let cookie = requestCookies

configDefault = {headers: {

'X-Requested-With': 'XMLHttpRequest',

cookie

}

}

// config = configDefault

}

config = configDefault

let datas = type === 'get' ? {params: data} : data

return Vue.axios[type](url, datas, config)

.catch(response => {

/* eslint-disable prefer-promise-reject-errors */

return Promise.reject({code: 500, message: '服务器繁忙!'})

})

.then((response) => {

// 统一loading

// store.commit('showAjaxLoading',false)

let {data} = response

if (typeof data === 'string') { // 转换返回json

data = JSON.parse(data)

}

console.log(data)

if (data && data.code == 200) {

// Promise.reject(data)

// 为什么不是router.query??

var redirect = router.currentRoute.query.redirect

if (redirect) {

console.log(redirect)

// 用location 不会报promise错,用router的跳转会报错

location.href = redirect

Promise.reject(data)

}

// 请求成功

return data

}

if (data.code === 400) {

// 统一报错弹窗

// store.commit('showAjaxMessage',true)

return data

}

if (data && data.code === 401) { // 没有登录权限

// router.replace({

// name: 'not',

// query: {redirect: router.currentRoute.path}

// })

// return data;

// location.href = '/#login'

// router.push('login?redirect='+router.currentRoute.path)

// router.push({ path: 'login', query: { redirect: router.currentRoute.path }})

// 用location 不会报promise错,用router的跳转会报错

// location.href = '/login?redirect='+router.currentRoute.path

// Promise.reject(data)

// console.log(router.currentRoute)

return data.data

} else {

return data;

}

return Promise.reject(data)

})

.catch(err => {

return Promise.reject(err)

})

}

发起带 cookies 参数的请求

export default {

name: 'Test',

data () {

return {

title:'服务端渲染test',

data: this.$store.state.count

}

},

mounted () {

},

created () {

// 检查cookie,ssr与spa不一样的地方

makelaravelcookie(this.$store.state.cookies)

console.log('this.$store.state.count')

console.log(this.$store.state.count)

},

asyncData ({ store, route }) {

console.log('asyncData')

// 触发 action 后,会返回 Promise

return store.dispatch('increment',store)

},

computed: {

user () {

// return 31

return this.$store.state.count

}

},

// seo

title () {

return this.user

},

}

vue 服务端渲染是通过asyncData来获取数据的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值