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>

 

第一部分就到这里。


posted @ 2019-08-15 12:59  Jason齐齐  阅读(697)  评论(0编辑  收藏  举报