vue服務端渲染——即SSR
文章轉自悠揚小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 服務器端渲染),本文主要說明使用兩種
兩個示例的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
、代碼檢查ESLint
、Standard
,沒有選擇集成測試與單元測試,安裝包太耗時了。
初始化完畢後:
cd vue-prerender-demo npm install npm run dev
進入項目,安裝完畢,啟動項目,確保項目正常工作。
1.3 配置
為了方便測試效果,我對初始化好的 demo 做了以下修改:
- 將路由的
mode
修改為history
- 增加一個Test組件,與Hello組件評級,作為一個單獨的路由頁面
- 修改
router/index.js
中的配置,增加/test
路由。 - 在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,那麽在通用代碼
中,我們有必要並且需要遵守下面的這些約定:
通用代碼: 在客戶端與服務器端都會運行的部分為通用代碼。
- 註意服務端只調用
beforeCreat與created
兩個鉤子,所以不可以做類似於在created
初始化一個定時器
,然後在mounted或者destroyed
銷毀這個定時器
,不然服務器會慢慢的被這些定時器給榨幹了 - 因單線程的機制,在服務器端渲染時,過程中有類似於
單例
的操作,那麽所有的請求都會共享這個單例的操作,所以應該使用工廠函數
來確保每個請求之間的獨立性。 - 如有在
beforeCreat與created
鉤子中使用第三方的API,需要確保該類API在node
端運行時不會出現錯誤,比如在created
鉤子中初始化一個數據請求的操作,這是正常並且及其合理的做法。但如果只單純的使用XHR
去操作,那在node
端渲染時就出現問題了,所以應該采取axios
這種瀏覽器端與服務器端
都支持的第三方庫。 - 最重要一點: 切勿在通用代碼中使用
document
這種只在瀏覽器端可以運行的API,反過來也不可以使用只在node
端可以運行的API。
2.3 準備工作
使用 vue-cli
再次初始化一個項目: 這裏我只選擇了選擇了vue-router
、沒選選擇代碼檢查ESLint
、Standard,
後面有一個很小的差異,到時候會特別註明
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