前言:
服务端渲染,简明的说就是在服务端获取数据并进行解析渲染,直接生成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>
第一部分就到这里。