阅读 0

vue 2.0服务端渲染从零开始(二)

转载:https://www.jianshu.com/p/bba6adef51cf

编写通用代码

编写通用代码时的约束条件:即运行在服务器和客户端的代码,由于用例和平台API的差异,当运行在不同环境中时,我们的代码将不会完全相同。

Vue.js 服务器端渲染指南--编写通用代码中详细的介绍了需要注意的几个方面:

  • 服务器上的数据响应
    • 独立的应用程序实例
    • 禁用数据响应
  • 组件生命周期钩子函数
    • 只有 beforeCreatecreate会在服务端渲染(SSR)过程中被调用。
    • 副作用代码移动到beforeMountmounted生命周期中。
  • 访问特定平台API
    • 仅浏览器可用的全局变量windowdocument,在纯客户端的生命周期钩子函数中惰性访问它们。
    • 尽可能使用通用API,例如axios可以向服务器和客户端都暴露相同的API
  • 自定义指令
    • 推荐使用组件作为抽象机制,并运行在「虚拟 DOM 层级(Virtual-DOM level)」(例如使用渲染函数render function)
    • 如果自定义指令不是很容易替换为组件,则可以在创建服务器renderer时,使用directives选项提供的"服务器端版本"

避免状态单例

同样是单例对象(vue实例),在纯客户端代码时,vue实例在组件创建是生成,在组件销毁后跟着从内存中清除。

但是Node.js服务器是一个长期运行的进程。创建的vue实例将一直留存在内存中,导致它被每个传入的请求共享,这样很容易导致交叉请求状态污染。

因此,我们不应该直接创建一个应用程序实例,而是应该暴露一个可以重复执行的工厂函数,为每个请求创建新的应用程序实例。

工厂模式:
app.js

const Vue = require('vue')

module.exports = function createApp (context) {
  return new Vue({
    data: {
      url: context.url
    },
    template: '<div>访问的 URL 是:{{ url }}</div>'
  })
}
复制代码

server.js

 const createApp = require('./app')
  
 const app = createApp(context)
复制代码
完整示例

const createApp = require('./app')
const server = require('express')();
const renderer = require('vue-server-renderer').createRenderer({
	template: require('fs').readFileSync('./app.template.html', 'utf-8')
});

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

  const context = {
	  title: '你好,VUE SSR!',
	  meta: `<meta name="description" content="Vue.js 服务端渲染指南">`,
	  url: req.url
	}
	
  const app = createApp(context)
  
  renderer.renderToString(app, context, (err, html) => {
    if (err) {
      res.status(500).end('Internal Server Error')
      return
    }
	res.setHeader('Content-Type','text/html;charset=UTF-8'); // 避免乱码
    res.end(html)
  });
})

server.listen(8080, () =>{
	console.log('服务器启动成功');
});
复制代码


同样的规则也适用于 router、store 和 event bus 实例。你不应该直接从模块导出并将其导入到应用程序中,而是需要在 createApp 中创建一个新的实例,并从根 Vue 实例注入。


关注下面的标签,发现更多相似文章
评论