Vue服务端渲染有个参数runInNewContext,之前我们这个参数一直设置为true,这样可以全局获取到直出的context,进而获取context里面的reqest对象,通过reqest对象拿到cookie和ua。类似下面这样。
//在处理请求的server.js中,注入cookie到context
const context = {
url: req.url,
cookies: req.cookies
}
renderer.renderToString(context, (err, html) => {
if (err) {
return errorHandler(err)
}
res.end(html)
})
//在需要用的cookie的地方通过__VUE_SSR_CONTEXT__获取
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
}
然而,runInNewContext设置为true会有比较明显的性能开销。为了优化性能,需要把runInNewContext设置为false或者once,随之而来的问题是,我们再也不能在服务端通过__VUE_SSR_CONTEXT__变量拿到请求的context对象,也就拿不到cookies和user-agent
百度和google上面很多vue服务端渲染的实现都是这样用过store透传cookies实现的。主要的实现核心是这里,通过server-entry处理asyncData方法的时候,把context里面注入的cookie传给asyncData方法,类似这样。
//server-entry.js 服务器处理asyncData的时候,透传cookie
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)
这篇文章有详细的介绍再说 Vue SSR 的 Cookies 问题
domain是node一个处理异步错误捕获的模块,它有一个特性,就是domain包裹的代码里面运行的时候,process.domain会指向当前这个domain,利用这个特性,我们可以把req对象挂载在domain对象里面,这样我们在服务端的时候,通过process.domain.reqest,拿到这次请求的request对象,进而拿到cookie。
实现类似这样。
//server.js,创建domain包裹渲染方法
let d = domain.create();
d.add(req);
d.add(res);
d.request = req;
d.response = res;
d.on('error', function(err) {
res.end(500,'error')
})
const context = {
title: 'Vue HN 2.0', // default title
url: req.url,
request:req
}
d.run(function() {
renderer.renderToString(context, (err, html) => {
if (err) {
return handleError(err)
}
res.send(html)
if (!isProd) {
console.log(`whole request: ${Date.now() - s}ms`)
}
})
})
//cookie.js,封装cookie.js
let data = {}
Object.defineProperty(data,'cookie',{
get:function(){
if(process.domain){
return process.domain.request.headers.cookie
}else{
return document.cookie
}
}
})
module.exports = data
1.runInNewContext为ture,使用vue自带的__VUE_SSR_CONTEXT__ 来获取cookie,优点是简单粗暴,不需要太多改造,缺点是性能消耗大
2.通过透传request,性能最好的一种方式,纯透传request对象。缺点是组织代码麻烦,任何需要cookie和user-agent的地方,都需要透传req对象。
3.通过domain挂载request,有一定性能开销,但是和第一种方式一样,可以引入一个变量,直接通过这个变量获取cookie
参考资料
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。