1. 程式人生 > >vue服務端渲染——即SSR

vue服務端渲染——即SSR

sset install r.js 層次 約束 分享 錯誤 一點 首頁

文章轉自悠揚小Q,原文地址: 
http://blog.myweb.kim/vue/%E8%AE%A9vue-cli%E5%88%9D%E5%A7%8B%E5%8C%96%E5%90%8E%E7%9A%84%E9%A1%B9%E7%9B%AE%E9%9B%86%E6%88%90%E6%94%AF%E6%8C%81SSR/?utm_campaign=ligang&utm_source=csdn&utm_medium=blog

當前 SPA 架構流行的趨勢如日中天,但在 SEO 方面好像一直是個痛點,所以眾多流行的 mv* 等框架也為此痛點提出了解決方案。
vue 官方提供了快速構建項目的工具 vue-cli,其方便快捷性眾所周知。本文章來分享一下使用vue cli構建項目後如何集成 SSR(server side render 服務器端渲染),本文主要說明使用兩種

方式來實現SSR的效果。

兩個示例的git地址:

    • vue-prerender-demo
    • vue-ssr-demo
此文章面向對 vue 較為熟悉以及對 vue-cli 有些許了解的同學。

我的環境

  • node v10.13.0
  • npm v6.9.0
  • vue-cli v2.9.6
  • Windows 10(第一次測試未在linux‘服務器上進行)

以上並不是重要因素~~

方式一並未測試,方式二成功渲染

方式一:使用prerender-spa-plugin插件獲得SSR的效果。

1.1 說明

插件地址:prerender-spa-plugin

嚴格上來說,此種實現方式並非叫做 SSR,而是預渲染。不過效果上是一樣的,甚至某種程度上來說可能要比 SSR 更好。相比官方提供的 SSR 繁瑣配置,prerender 配置更簡單快捷,如無特殊要求只需在 webpack 中加一個 plugin 的配置即可。 但是此方式只支持h5 history方式的路由,不支持hash方式的路由。

技術分享圖片

prerender 主要是利用phantom js模擬瀏覽器環境,將指定的路由頁面放在 phantom j s中運行,這樣.vue便會在 phantom 中工作並完成渲染,prerender再去獲取渲染後的dom結構並將其寫入對應路由的 html 文件。


服務啟動後,在真實瀏覽器環境中輸入對應的路由地址,服務器便會將 prerender 已渲染好生成的 html 返回給瀏覽器,從而達到了 SSR 的效果。

1.2 初始化

確保 vue-cli 安裝成功,執行命令:

vue init webpack vue-prerender-demo //本篇文章都是在webpack基礎上配置的

回車之後構建工具會提示一些項目信息的相關設置。方式一中我選擇了vue-router、代碼檢查ESLintStandard,沒有選擇集成測試與單元測試,安裝包太耗時了。

初始化完畢後:

cd vue-prerender-demo
npm install
npm run dev

進入項目,安裝完畢,啟動項目,確保項目正常工作。

1.3 配置

為了方便測試效果,我對初始化好的 demo 做了以下修改:

  1. 將路由的mode修改為history
  2. 增加一個Test組件,與Hello組件評級,作為一個單獨的路由頁面
  3. 修改router/index.js中的配置,增加/test路由。
  4. 在Hello組件中加入了<router-link to="/test">/test</router-link>, 在Test組件中加入了<router-link to="/">回到首頁</router-link>

在此之後查看頁面,從首頁->Test->首頁之間跳轉,路由可正常工作。

1.4 開始

那麽接下來即可開始正式工作:

(1). 安裝 prerender-spa-plugin, 因為依賴phantom js,phantom 的安裝比較蛋疼,太耗時了~

npm install prerender-spa-plugin -D

(2). 開始 prerender 相關的配置:

修改 webpack.prod.conf.js,只在生產環境進行預渲染。

 //引用
  var PrerenderSpaPlugin = require(prerender-spa-plugin)
  //...
  plugins: {
      //....
      //配置 prerender-spa-plugin
      new PrerenderSpaPlugin(
          // 生成文件的路徑,此處與webpack打包地址一致
          path.join(config.build.assetsRoot), //config.build.assetsRoot為vue cli生成的配置,打包後的文件地址
          // 配置要做預渲染的路由,只支持h5 history方式
          [ /, /test]
      )
      //....
  }   

(3). 編譯

運行命令:

npm run build

等待命令完成後,可以看到 dist 目錄下的文件結構:

技術分享圖片

相比原配置打包出來的內容多出了一個test目錄,此目錄對應prerender配置中的/test路由,那麽配置的/就是dist/index.html嗎?對的,是這樣。

? 打開dist/index.html查看一下內容,此文件內有很多東西,不再是以前孤單單的一個<div id="app"></div>,現在body裏面的dom結構其實是與在瀏覽器中渲染的/路徑頁面dom結構是一致的!test/index.html便是對應訪問/test渲染後的dom結構。

(4). 驗證

可忽略此步驟。 這裏面使用了python作為快速啟動的server。

為了在真實環境中確認最終效果是正確的,我在本地使用 python 啟動了一個 http 服務(沒有使用 webpack 與 node 作為服務)

cd dist //進入到對應目錄
python -m SimpleHTTPServer 8888 //將dist作為根目錄,啟動8888端口,

在瀏覽器中直接輸入localhost:8888/test,並右鍵選擇查看顯示網頁源代碼

技術分享圖片

/test的 response 內容中我們可以看到返回的是渲染之後的 dom 結構,搜索引擎的小蜘蛛可以順利的獲取到內容,從而達到了 SEO 的效果。

2.5 優缺點

簡單、易上手、無需配置即可滿足基本的 SEO 要求

只支持h5 history

不適合頻繁變動的頁面,如果這個頁面希望做SEO優化。因為預渲染只是類似於快照的概念。

此方式實現的 demo 地址: vue-prerender-demo

方式二:使用官方提供的輪子在node端做SSR

2.1 說明

本示例只說明如何完成一個相對基礎的 SSR,vuex以及緩存等可參考官網說明。

官方文檔地址:https://ssr.vuejs.org/zh/

官方文檔開篇便說明 「vue 與 library 的版本最低要求、為什麽使用 SSR 以及對比上面提到的 prerender-spa-plugin 插件」。

以及如下:

本指南將會非常深入,並且假設你已經熟悉 Vue.js 本身,並且具有 Node.js 和 webpack 的相當不錯的應用經驗。
如果你傾向於使用提供了平滑開箱即用體驗的更高層次解決方案,你應該去嘗試使用 Nuxt.js
它建立在同等的 Vue 技術棧之上,但抽象出很多模板,並提供了一些額外的功能,例如靜態站點生成。
但是,如果你需要更直接地控制應用程序的結構,Nuxt.js 並不適合這種使用場景。

官方 vue ssr demo : HackerNews Demo

相對於 prerender 插件來對比,SSR 上手復雜度可以用天差地別來形如了吧~~
跟隨本章節可以實現一個基礎版本的 SSR 構建配置。

2.2 約束

如果你打算為你的vue項目在node使用 SSR,那麽在通用代碼中,我們有必要並且需要遵守下面的這些約定:

通用代碼: 在客戶端與服務器端都會運行的部分為通用代碼。
  1. 註意服務端只調用beforeCreat與created兩個鉤子,所以不可以做類似於在created初始化一個定時器,然後在mounted或者destroyed銷毀這個定時器,不然服務器會慢慢的被這些定時器給榨幹了
  2. 因單線程的機制,在服務器端渲染時,過程中有類似於單例的操作,那麽所有的請求都會共享這個單例的操作,所以應該使用工廠函數來確保每個請求之間的獨立性。
  3. 如有在beforeCreat與created鉤子中使用第三方的API,需要確保該類API在node端運行時不會出現錯誤,比如在created鉤子中初始化一個數據請求的操作,這是正常並且及其合理的做法。但如果只單純的使用XHR去操作,那在node端渲染時就出現問題了,所以應該采取axios這種瀏覽器端與服務器端都支持的第三方庫。
  4. 最重要一點: 切勿在通用代碼中使用document這種只在瀏覽器端可以運行的API,反過來也不可以使用只在node端可以運行的API。

2.3 準備工作

使用 vue-cli再次初始化一個項目: 這裏我只選擇了選擇了vue-router、沒選選擇代碼檢查ESLintStandard, 後面有一個很小的差異,到時候會特別註明

vue init webpack vue-ssr-demo

然後

cd vue-ssr-demo
npm install
npm run dev

確保初始化的項目可正常運行,接下來開始慢慢折騰吧~~

2.4 開始折騰

(1). 首先安裝 ssr 支持

npm i -D vue-server-renderer

重要的是 vue-server-renderer 與 vue 版本必須一致匹配

(2). 增加路由test與頁面

新建Test.vue文件並添加路由,並在其中隨便寫了個計數器,以驗證服務端渲染時,vue 的機制會正常工作。

 <template>
    <div>
      Just a test page.
      <div>
        <router-link to="/">Home</router-link>
      </div>
      <div><h2>{{mode}}</h2></div>
      <div><span>{{count}}</span></div>
      <div><button @click="count++">+1</button></div>
    </div>
  </template>
  <script>
    export default {
      data () {
        return {
        mode: process.env.VUE_ENV === server ? server : client,
          count: 2
        }
      }
    }
  </script>

(3). 在src目錄下創建兩個js:

   src
   ├── entry-client.js # 僅運行於瀏覽器
   └── entry-server.js # 僅運行於服務器

(4). 修改router配置。

無論什麽系統路由總是最重要的,服務器端渲染自然也要公用一套路由系統,並且為了避免產生單例的影響,這裏主要只為每一個請求都導出一個新的router實例:

   import Vue from ‘vue‘
   import Router from ‘vue-router‘
   import HelloWorld from ‘@/components/HelloWorld‘

   Vue.use(Router)

   export function createRouter () {
     return new Router({
       mode: ‘history‘, // 註意這裏也是為history模式
       routes: [
         {
           path: ‘/‘,
           name: ‘Hello‘,
           component: HelloWorld
         }, {
           path: ‘/test‘,
           name: ‘Test‘,
           component: () => import(‘@/components/Test‘) // 異步組件
         }
       ]
     })
   }

vue服務端渲染——即SSR