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當中,固然用戶也可以取消,自行選擇手動嵌入的內容

相關文章
相關標籤/搜索