前幾天瞭解了下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) }) }