Vue.js SSR 内容总结

本文只是对Vue.js 官方SSR文档和对 官方hackernews demo的我的学习总结,说得不够完整的请见谅

本文主要对如下几方面内容对Vue.js SSR的内容进行分析总结javascript

  • SSR出现的缘由
  • Vue.js SSR的整体原理
  • SSR当中的数据预取
  • SSR在编写代码时候的限制
  • SSR的webpack构建原理

SSR出现的缘由

  1. 单页应用有一个很大的缺点就是SEO问题,搜索引擎目前只能对同步的javascript进行索引,但对于须要异步获取数据的单页应用来讲,搜索引擎并不会抓取到它们的内容
  2. 更快的首屏内容展现速度,单页应用须要等待JS文件加载完成,而后再进行页面渲染,而SSR是将渲染完毕的html传输给客户端

Vue.js SSR的整体原理

若是用一句话归纳Vue.js SSR的运做过程,那就是在服务端将Vue.js实例转换成html字符串传输到客户端,而后进行客户端激活,使网页内容能在Vue实例的控制之下html

这一句话包含两步内容vue

  1. Vue.js实例转换成html字符串
  2. 客户端激活

先来看第一步java

Vue.js应用转换成html字符串

一个最简单的Vue.js单页应用是这样的:webpack

new Vue({
    render: h => h('div', '123')
}).$mount('#app')

这里也包含两步git

  1. 新建Vue实例
  2. 挂在到DOM上面

在服务端当中咱们不进行上面第二步操做,取而代之的是将这个实例直接渲染成字符串,作这个工做的就是咱们的vue-server-renderergithub

const renderer = require('vue-server-renderer').createRenderer()
const Vue = require('vue')

renderer.renderToString(new Vue({
  render: h => h('div', 123)
})).then(html => {
  console.log(html)
}).catch(err => {
  console.error(err)
})
// 输出<div data-server-rendered="true">123</div>

到如今一个最简单的vue ssr应用在服务端的工做已经完成了,下面咱们转向下一步客户端激活web

客户端激活

客户端激活跟咱们单页应用所作的工做相比,最大的不一样点就是它并不会构建DOM元素,只会对现有的DOM元素进行激活,使它们能被Vue实例进行控制,而判断激活的关键就是上面的data-server-rendered属性vue-router

至此,最简单的一个SSR应用已经构建完成了,下面是对这个应用的功能进行进一步的补充vuex

SSR当中的数据预取

数据预取包含着两个方面,客户端的数据预取和服务端的数据预取

服务端的数据预取

咱们渲染一个内容完整页面的时候每每须要向服务器请求数据,因此如今服务端的逻辑变成等待数据获取完毕,而后将页面转换成html字符串

其中数据获取有如下几个问题:

  1. 获取哪些数据?
  2. 如何获得获取数据的方法?
  3. 应在什么时候预取数据?
  4. 预取的数据应保存在哪里?
  5. 预取的数据应该怎么样跟客户端进行同步?

问题1:
咱们的数据用来渲染页面,那么咱们就须要组成当前页面的全部组件各自所须要的数据

问题2:
每一个须要进行服务端数据预取的组件定义一个asyncData方法,此方法用于数据预取

问题3:
咱们须要先获得当前页面全部须要渲染的组件,而后再进行数据预取

问题4:
因为还须要进行数据同步,因此很难将数据保存在组件的私有data上面,放在vuex上面是个广泛的选择

问题5:
服务端在返回html字符串的时候,store数据将被序列化之后以window.__INITIAL_STATE__=/* store state */的形式插入到脚本当中被客户端获取,客户端的store使用store.replaceState方法同步state

简单复述一下上面的流程就是:
在渲染当前页面的全部组件加载完毕之后,执行这些组件的asyncData方法,这些方法将获取到的数据将由vuex托管,获取数据完毕之后便可将应用渲染成html字符串,vuex store的state将会被序列化之后一并传输到客户端,被客户端进行同步

下面是实现的一些细节:

  1. 判断组件加载完毕的方法是vue-router的onReady方法
  2. 获取当前页面的全部组件为vue-router的getMatchedComponents方法

因为源码太长因此没贴出来,具体能够到官网浏览

服务端数据预取的关键点算是总结的差很少了,下面简单说一下客户端的数据预取

客户端数据预取

客户端的数据预取方法可分为两种:

  1. 等待数据获取完毕后再进行视图切换
  2. 先进行视图切换而后在进行数据获取

两种方法区别在于让用户在何时产生等待的感受,第一种是在页面切换时,而第二种是在页面切换完毕等待内容的出现时

第一种方法的实现使用了vue-router实例的beforeResolve方法,这个方法执行在异步组件加载完毕后,导航被确认以前,当完成数据预取之后router才会进行DOM更新等步骤

第二种方法的实现跟咱们通常进行数据获取一致,在beforeMount钩子当中执行

SSR在编写代码时候的限制

  1. 因为浏览器特定的API将会在服务端报错,如'document'、'window'等,尽可能避免使用此类API或者在非服务端运行的声明周期函数中调用如'mounted'等等
  2. 指令因为能直接操做DOM会受到很大的限制

SSR的webpack构建原理

以官方的hackernews demo为例,webpack有两个入口entry-cliententry-server分别负责构建客户端和服务端的文件

服务端方面webpack会输出一个名叫vue-ssr-server-bundle的json文件,此文件由官方提供的VueSSRServerPlugin插件所构建而成,是服务端的构建清单,传入createBundleRenderer生成服务端渲染所须要的renderer

客户端方面webpack输出的是由代码分割而成的chunk和公用bundle,与通常单页应用的构建类似,不一样的是会生成一个vue-ssr-client-manifest,此文件是客户端方面的构建清单,包含全部chunk的信息,将其传入上面的renderer当中能自动将chunk嵌入到html当中,固然用户也可以取消,自行选择手动嵌入的内容

相关文章
相关标签/搜索