Skip to content
On this page

vue ssr及需要掌握的点

讲些别人没有讲到的,前提是看完了官方的教程,另外,一篇文章肯定是讲不完的,此处将持续更新。

vue ssr本身之外涉及的点

vue ssr整体原理

在前后端分离的背景下,ssr(服务端渲染)就是做类似php和java模版引擎做的事情

so,用node做服务器,在访问vue 客户端路由的时候,匹配出涉及到的组件,即getMatchedComponents,检查这些组件是否需要服务端的数据渲染,即组件内置method asyncData。在所有涉及到的接口都返回后,将数据以context传递给html拼接,window.__INITIAL_STATE__,这就是server 端所做的事情。

到了客户端挂载的时候,需要将服务端之前取过的数据,即window.__INITIAL_STATE__状态对接,即官方的混合,其次,如果客户端存在需要预取数据的组件,还要从这些组件中筛选出当前没有被服务端渲染过的,再去请求拿数据存到store里。

以上都是构建之外的代码逻辑,还有很重要的一点就是构建。

服务端的打包,就是将客户端中需要在服务端渲染的代码映射成一个json文件,即server-bundle.json,通过bundleRenderer去渲染从接口获取的数据,并拼接需要引用哪些模块的js文件即clientManifest里标注的,然后根据给定的模版拼接好返回给express响应请求,最后去执行客户端打包生成的文件,client-bundle,执行客户端的逻辑。

image

源码结构:

shell
src
├── components
   ├── Foo.vue
   ├── Bar.vue
   └── Baz.vue
├── App.vue
├── app.js # 通用 entry(universal entry)
├── entry-client.js # 仅运行于浏览器
└── entry-server.js # 仅运行于服务器

vue ssr路由与数据(router与store)的混合

router与store同app.js里创建vue实例原理一样,需要创建一个工厂函数来返回新的实例

因为运行在服务端的代码是保存在内存中的,有且仅有一份,这么做是为了使不同的客户端得到不同的实例。

路由

路由对应的组件应该是按需加载的,和在客户端创建vue实例一样

js
export function createRouter() {
  return new Router({
    // 只能使用history,因为hash的变化express检测不到
    mode: 'history',
    routes: [
      {
        path: '/:id',
        component: r => require.ensure([], () => r(require('../views/Index.vue')), 'Index')
      }
    ]
  })
}

不同的是,由于组件是异步的,需要等到所有组件加载完成之后才能创建实例并开始走流程。

在访问一个地址后,会push到router中,利用vuex-router-sync,将router与同步到store中,以便保存这个“数据快照”即window.__INITIAL_STATE__

数据

在路由加载完成后,会根据当前路由匹配出需要渲染的组件去取数据,此时会调用组件构造函数上的一个方法(非实例)即官方的asyncData(可随意命名),将当前storerouter作为参数传递给它

js
asyncData({ store, route }) {
    return store.dispatch('fetchItem', route.params.id)
},

这样它就可以获取数据并保存在store中。

最重要的混合步骤是在client-entry中初始化时做的

js
// entry-client.js

const { app, router, store } = createApp()

if (window.__INITIAL_STATE__) {
  store.replaceState(window.__INITIAL_STATE__)
}

【参考】

自动化部署流程图

image

【参考】