前面的几篇里,我们都没有涉及需要从后台抓取数据来渲染的页面,这块可能是最复杂的部分了,本文里我们就来讨论这个问题 – Vue SSR 如何做后台数据预取

我们面临什么样的难题?

如果一个页面需要从数据后台的 api 获取数据来渲染页面,那么从 SSR 的架构来说就要处理以下2个场景:

  1. 这个页面不是首屏

    数据应该由前端去数据后台获取,并渲染页面。这个场景和普通的 client side Vue 项目基本一样。

  2. 这个页面是首屏

    数据应该由后台获取,因为这个作为用户访问的首屏,是要由 server-bundle 渲染生成 index.html (壳子 HTML) 的。HTML 页面和 client-bundle 一起返回给浏览器后, 在浏览器端做 hydrate。

    这问题就又来了,client-bundle 并没有后台的那份数据。数据都不一致,hydrate 根本无从谈起。怎么办呢?可能 2 个思路:

    • client-bundle 再去后台拿一次。细想一下完全不可行。首先,这是对数据后台的重复开销,能避免就应该避免。其次,对同一个 api 接口的2次调用,未必能得到同样的数据(比如获取论坛最新帖子的api),数据不同的话,hydrate 还是会失败。
    • 把后台的这份数据想办法返回给前台。Bingo!Vue 的 SSR 就是这么做的。(我想可能所有的 SSR 方案都得这么做)

余文中我们主要分析场景2,即这个页面是首屏的场景。这个页面不是首屏的场景相对简单,我们下一篇再说。

Vue SSR 的方案

数据在 server-bundle 和 client-bundle 之间共享,看到数据共享几个字眼,可能大家就很自然的想起来 Vuex. Vue 的 SSR 中也确实是以 Vuex 为基础的。如大致的流程,上图所示:

方案很完美,但是为了做到前后台代码同构,实现还是挺复杂的。

Vue SSR 实现

总结

以上就是 Vue SSR 处理首屏需要加载数据问题的思路和方案。基本上就是用 Vuex 为容器,以 index.html (序列化 state) 为载体来共享前后台数据,这个过程被 Vue SSR 官方文档形象的称为服务端数据预取。不过目前我们只解决了场景1,并没有解决场景2(页面不是首屏)。

我们可以这样体验一些场景2的问题,运行上面提到的示例代码后,我们首先访问 Home 页,然后跳转到 Test 页,此时 Test 页面不会加载数据。

下一篇,我们再来讨论这个问题。

系列文章: