概念
- 客戶端渲染:在瀏覽器端進行渲染,服務端返回的只是 <div id="app"></div> 的空標簽文檔妓布;
- 服務端渲染:在服務器就做好數(shù)據(jù)的的拼接姻蚓,請求返回的 html 是完整的文檔。
客戶端渲染匣沼,服務端渲染對比
- 客戶端渲染不利于 SEO 搜索引擎優(yōu)化(返回的是空標簽)狰挡;
- 服務端渲染出來的文檔可以被爬蟲抓取,客戶端異步渲染很難被爬蟲抓仁吞巍加叁;
- 服務端渲染直接將 HTML 字符串傳遞給瀏覽器,大大加快了首屏加載時間它匕;
- 服務端渲染占用更多的 CPU 和內(nèi)存資源;
- 在服務端渲染模式下窖认,一些常用的瀏覽器 API 可能無法正常使用(服務端沒有 document豫柬,window);
- 服務端渲染只支持 vue 中 beforeCreate 和 created 兩個生命周期(因為沒有 dom,所以不涉及 mounted 等)
SSR 運行過程:
- 服務端渲染只是做首屏的渲染扑浸;
- 后續(xù)在瀏覽器中的路由切換邏輯執(zhí)行的是客戶端渲染(前端路由切換頁面烧给,每個路由返回的首屏是服務端來做)
- 服務端渲染使用 Node 服務來實現(xiàn)(前后端分離模式)
- 傳統(tǒng)的服務端渲染是 jsp asp php+smarty,不適合前后端分離開發(fā)模式
整個打包過程
- 首先要保證客戶端渲染模式下可以跑起來首装,然后提供一個服務端入口
- 通過將一份代碼打包出來兩份邏輯(客戶端和服務端)
- 前端拿到打包出來的 bandle.js,后端通過打包的結果渲染出字符串返回給瀏覽器
-
瀏覽器展示 = 前端 bundle.js + 服務端渲染的字符串
如下圖:展示了打包過程:
安裝包
- vue vue-server-renderer(通過vue-server-renderer來實現(xiàn)vue的服務端渲染)
- koa koa-router(通過 node 來做服務端)
npm install vue vue-server-renderer koa @koa/router -D
開發(fā)中
本地新建一個文件夾 vue-ssr-demo杭跪,初始化項目npm init -f
仙逻,生成一個package.json,npm install
安裝需要用到的包涧尿,新建一個server.js
來啟動服務:
// server.js
const Vue = require('vue')
const VueServerRenderer = require('vue-server-renderer')
const vm = new Vue({
data() {
return {
name: '小可愛',
age: 3
}
},
template: `<div>我是:{{name}}系奉,{{age}}歲</div>`
})
const Koa = require('koa')
const Router = require('@koa/router')
// 創(chuàng)建一個渲染器
const render = VueServerRenderer.createRenderer()// 創(chuàng)建一個渲染器
let app = new Koa() // app實例
let router = new Router() // 路由實例
router.get('/', async (ctx) => {
ctx.body = await render.renderToString(vm) // render.renderToString 返回的是一個promise
})
app.use(router.routes())
app.listen(3500)
啟動命令:nodemon server.js
,VueServerRenderer.createRenderer()創(chuàng)建一個渲染器姑廉,調(diào)用渲染器 renderToString
方法 傳入vm實例
缺亮,訪問http://localhost:3500/ 可以看到頁面展示:
頁面上顯示了
data-server-rendered="true"
表示服務端渲染。
通常我們都是有一個 html 模板桥言,然后將打包的內(nèi)容放進去萌踱,新建一個 html 文件葵礼,寫下vue server
的標記
<!--vue-ssr-outlet-->
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue ssr template</title>
</head>
<body>
<!--vue-ssr-outlet-->
</body>
</html>
server.js
中讀取本地的index.html
文件,文件內(nèi)容作為渲染器模板即可:
const Vue = require('vue')
const VueServerRenderer = require('vue-server-renderer')
const vm = new Vue({
data() {
return {
name: '小可愛',
age: 3
}
},
template: `<div>我是:{{name}}并鸵,{{age}}歲</div>`
})
const Koa = require('koa')
const Router = require('@koa/router')
const fs = require('fs')
const path = require('path')
const htmlStr = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf8') // 同步讀取文件
// 創(chuàng)建一個渲染器
const render = VueServerRenderer.createRenderer({
// 可以從本地讀取html文件當作模板
template: htmlStr, // 采用哪個模版去渲染,在html中加入這個<!--vue-ssr-outlet-->標簽表示渲染到這個位置上
}) // 創(chuàng)建一個渲染器
let app = new Koa() // app實例
let router = new Router() // 路由實例
router.get('/', async (ctx) => {
// ctx.body = 'hello world'
ctx.body = await render.renderToString(vm) // render.renderToString 返回的是一個promise
// // <div data-server-rendered="true">我是:hcj鸳粉,20歲</div>
})
app.use(router.routes())
app.listen(3500)
監(jiān)聽文件改動,自動重啟服務
npm install nodemon -g
目前實現(xiàn)了一個最簡單的 ssr园担,后續(xù)文章加入客戶端配置届谈,服務端配置,vue-router弯汰, vuex 來實現(xiàn)完整的 ssr艰山。
github:https://github.com/mxcz213/vue-ssr-demo/tree/part-one