
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 = data1.runInNewContext为ture,使用vue自带的__VUE_SSR_CONTEXT__ 来获取cookie,优点是简单粗暴,不需要太多改造,缺点是性能消耗大
2.通过透传request,性能最好的一种方式,纯透传request对象。缺点是组织代码麻烦,任何需要cookie和user-agent的地方,都需要透传req对象。
3.通过domain挂载request,有一定性能开销,但是和第一种方式一样,可以引入一个变量,直接通过这个变量获取cookie
参考资料
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。