vue-ssr的實現原理連載(一)
前言:
服務端渲染,簡明的說就是在服務端獲取資料並進行解析渲染,直接生成html片段返回給瀏覽器。
優缺點:
服務端渲染能解決的問題: 1.SEO問題,前端動態渲染的內容是不能被搜尋蜘蛛抓取的。2.首屏載入過程慢。SPA在初始化首屏的時候需要載入所有的資源,這也是使用服務端渲染能折中解決的問題。
服務端渲染的缺點:1.增加伺服器的壓力。 2.同構似乎對前後端分離有所違背
vue-server-renderer
文件地址: https://ssr.vuejs.org/en/ 暫時沒有中文文件。下面來一步一步的說明實現過程。所有的原始碼都可以在我github上檢視,並且根據教程分了step,歡迎star。
vue-ssr的實現原理連載(一): https://github.com/Jasonwang911/vue-ssr/tree/master/step1
首先安裝相關依賴:
npm init -y yarn add koa koa-router koa-static vue vue-router vuex vue-server-renderer
先要確定vue的版本
vue & vue-server-renderer 2.3.0+ vue-router 2.5.0+ vue-loader 12.0.0+ & vue-style-loader 3.0.0+
vue-server-renderer 是vue官方用來實現vue服務端渲染的一個包。具體官方教程是: https://ssr.vuejs.org/zh/#%E4%BB%80%E4%B9%88%E6%98%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E6%B8%B2%E6%9F%93-ssr-%EF%BC%9F
新建server.js檔案,然後編寫一個最簡單的koa服務
const Koa = require("koa"); const Router = require("koa-router"); const Static = require("koa-static"); const app = new Koa(); const router = new Router(); router.get("/", ctx => { ctx.body = "hello vue-ssr"; }); app.use(router.routes()); app.listen(3000, () => { console.log(`node serve run at port 3000`); });
使用nodemon啟動 nodemon server.js, 開啟瀏覽器的 localhost:3000埠,可以看到 hello vue-ssr。
接下來,我們來進行一些改造,引入vue, 來建立一個vue的例項,然後引入 vue-server-renderer ,來去渲染我們的vue例項。這裡需要注意兩點, 1. 建立的vue的例項是在服務端使用的,所以並不能掛載元素,只能渲染template模板字串 2. vue-server-renderer 這個包可以幫我們建立一個渲染器render, 渲染器有很多方法 render.renderToString() 渲染成字串,render.renderToStream 渲染成流等等。需要注意的是 render.renderToString() 接收一個vue的例項並返回一個promise的字串,將返回的字串直接渲染到頁面上,注意這個方法是個非同步操作。
const Koa = require("koa"); const Router = require("koa-router"); const Static = require("koa-static"); const Vue = require("vue"); const VueServerRender = require("vue-server-renderer"); // 建立一個vue的例項,注意在服務端不能掛載元素,只能使用渲染模板字串 const vm = new Vue({ data() { return { msg: "hello vue-ssr" }; }, template: `<div>{{msg}}</div>` }); // 建立一個渲染器 let render = VueServerRender.createRenderer(); const app = new Koa(); const router = new Router(); // render.renderToString() 接收一個vue的例項並返回一個promise的字串,將返回的字串直接渲染到頁面上,注意這個方法是個非同步操作 router.get("/", async ctx => { ctx.body = await render.renderToString(vm); }); app.use(router.routes()); app.listen(3000, () => { console.log(`node serve run at port 3000`); });
儲存,nodemon 會自動幫我們更新服務,然後瀏覽器上仍舊會顯示 hello vue-ssr, 所不同的是在檢視網頁原始碼的時候,是以下的內容:
<div data-server-rendered="true">hello vue-ssr</div>
data-server-rendered="true" 的作用會在後面的小結說明,是為了效能的考慮,告訴瀏覽器這個是服務端渲染的,不需要進行diff操作,以節省效能的目的。
檢視完原始碼,你可能會說,這個缺少一個基本的html的頁面結構,現在我們就來一起實現:
首先,render渲染函式可以接受引數,引數中的template便是模板,我們可以將render.renderToString(vm)的結果插入到模板中的指定位置中去。這個指定位置是通過一個註釋標明的,首先我們建立模板檔案 template.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>vue-ssr</title> </head> <body> <!-- vue-ssr-outlet --> </body> </html>
<!-- vue-ssr-outlet --> 就是標明服務端渲染後的字串 <div data-server-rendered="true">hello vue-ssr</div> 將要插入的位置。
然後我們在koa服務中讀取模板檔案,並在渲染函式中配置這個模板檔案,讀取模板檔案使用了node的fs模組:
const fs = require("fs"); const template = fs.readFileSync("./template.html", "utf8");
完整程式碼:
server.js
const Koa = require("koa"); const Router = require("koa-router"); const fs = require("fs"); const Static = require("koa-static"); const Vue = require("vue"); const VueServerRender = require("vue-server-renderer"); // 建立一個vue的例項,注意在服務端不能掛載元素,只能使用渲染模板字串 const vm = new Vue({ data() { return { msg: "hello vue-ssr" }; }, template: `<div>{{msg}}</div>` }); const template = fs.readFileSync("./template.html", "utf8"); // 建立一個渲染器 let render = VueServerRender.createRenderer({ template }); const app = new Koa(); const router = new Router(); // render.renderToString() 接收一個vue的例項並返回一個promise的字串,將返回的字串直接渲染到頁面上,注意這個方法是個非同步操作 router.get("/", async ctx => { ctx.body = await render.renderToString(vm); }); app.use(router.routes()); app.listen(3000, () => { console.log(`node serve run at port 3000`); });
template.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>vue-ssr</title> </head> <body> <!--vue-ssr-outlet--> </body> </html>
第一部分就到這裡。