前几天了解了下vue 服务端渲染的流程,记录下。首先,什么是ssr(服务端渲染 Server Side Rendering),为何须要?html
先后端分离以后,页面加载的流程是,前端异步请求拿到数据渲染页面。服务端渲染就是在后端把数据取好,拼好页面的DOM树发给前端,到浏览器解析渲染。有没有想到先后端分离以前,由后端把数据塞进模版,前端负责显示的过去。(有没有种天下之势,合久必分,分久必合的感慨哈哈哈哈哈)前端
接下来,介绍下vue 服务端实现原理及流程。vue
用白话形容,服务端获取页面所需的数据以后,拼出html,把html转成string发送到前端,前端把html插入到指定节点,渲染页面,OK了。node
看看官网的demo,服务端怎么作的服务端数据预取。webpack
// entry-server.js import { createApp } from './app' export default context => { return new Promise((resolve, reject) => { const { app, router, store } = createApp() router.push(context.url) // 等到 router 将可能的异步组件和钩子函数解析完 router.onReady(() => { //获取相匹配的组件 const matchedComponents = router.getMatchedComponents() if (!matchedComponents.length) { return reject({ code: 404 }) } // 对全部匹配的路由组件调用 `asyncData()` Promise.all(matchedComponents.map(Component => { if (Component.asyncData) { return Component.asyncData({ store, route: router.currentRoute }) } })).then(() => { // 在全部预取钩子(preFetch hook) resolve 后, // 咱们的 store 如今已经填充入渲染应用程序所需的状态。 // 当咱们将状态附加到上下文, // 而且 `template` 选项用于 renderer 时, // 状态将自动序列化为 `window.__INITIAL_STATE__`,并注入 HTML。 context.state = store.state resolve(app) }).catch(reject) }, reject) }) }
html渲染好以后,转成string发到客户端,客户端插入到对应DOM节点下就能够啦~web
const { createBundleRenderer } = require('vue-server-renderer') const renderer = createBundleRenderer(serverBundle, { runInNewContext: false, // 推荐 template, // (可选)页面模板 clientManifest // (可选)客户端构建 manifest }) // 在服务器处理函数中…… server.get('*', (req, res) => { const context = { url: req.url } // 这里无需传入一个应用程序,由于在执行 bundle 时已经自动建立过。 // 如今咱们的服务器与应用程序已经解耦! renderer.renderToString(context, (err, html) => { // 处理异常…… res.end(html) }) }