为何要写本文呢,话说如今 vue-ssr 官网上对 vue 服务端渲染的介绍已经很全面了,包括各类服务端渲染框架好比 Nuxt.js 、 集成 Koa 和vue-server-renderer 的 node.js 框架 egg.js,都有本身的官网和团队在维护,文档真是面面俱到功能强大,可是,我我的在刚开始看这些资料的时候,老是忍不住发起灵魂三问:“我是谁?我在哪?我在干什么?”,提早没有相关知识的人开始学这些,确定是要走一些弯路或者卡在某个点一段时间的,因此我想把个人学习经验作下总结,一方面方便本身之后查阅,一方面也会在文中加一些针对官网上没有细说的点的理解,但愿能帮助你减小些学习成本,毕竟这是一个知识共享的时代嘛。本文不涉及到源码解析,主要讲解如何实现 vue 的服务端渲染,比较适合 vue-ssr 小白阅读,下面咱们进入正文:
ssr 的全称是 server side render,服务端渲染,vue ssr 的意思就是在服务端进行 vue 的渲染,直接对前端返回带有数据,而且是渲染好的HTML页面;而不是返回一个空的HTML页面,再由vue 经过异步请求来获取数据,再从新补充到页面中。html
这么作的最主要缘由,就是搜索引擎优化,也就是SEO,这更利于网络爬虫去爬取和收集数据。前端
这里简单说一下爬虫的爬取方式,爬虫经过访问 URL 获取一个页面后,会获取当前HTML中已存在的数据,也能够理解为把拿到的 HTML 页面转为了字符串内容,而后解析、存储这些内容,可是若是页面中有些数据是经过异步请求得到的,那么爬虫是不会等待异步请求返回以后才结束对页面数据的解析的,这样就会没有爬取到这部分数据,很不利于其余搜索引擎的收录。vue
这也就是为何单页面网站是不具有良好的SEO效果的,由于单页面返回的就是一个基本为空的 HTML 文件,里面就一个带有ID的元素等待挂载而已,页面的内容都是经过 js 后续生成的,好比这样:node
<!DOCTYPE html> <html lang="en"> <head><title>Hello</title></head> <body><div id="app"></div></body> <script src="bundle.js"></script> </html>
但对于不少公司来讲,公司的产品是但愿能被百度、谷歌等搜索引擎收录以后,进行排名,进一步的被用户搜索到,能更利于品牌的推广、流量变现等操做,要实现这些,就必须保证产品的网页是可以被网络爬虫爬取到的,显然一个完整的带有所有数据的页面更利于爬虫的爬取,固然如今也有不少方法能够去实现针对页面异步数据的爬取,github 上也开源了不少的爬虫代码,可是这显然对于爬虫来讲更加的不友好、成本更高。webpack
SSR 固然也是有着其余的好处的,好比首屏页面加载速度更快,用户等待时间更短等,其余更多概念能够查看官网 https://ssr.vuejs.org/zh/ ,这些官网上都有介绍。git
下面咱们结合官网上的代码,作一下代码实操,来加深下理解:github
在官网中,提供了一个使用模块 vue-server-renderer 简单实现 vue 服务端渲染的示例:
新建一个文件夹vue-ssr-demo,进入其中执行以下命令:web
// 安装模块 npm install vue vue-server-renderer --save
建立文件 server.jsnpm
// vue-ssr-demo/server.js 示例代码 //第一步,建立vue实例 const Vue = require('vue'); const app = new Vue({ template: "<div>hello world</div>" }); //第二步,建立一个renderer const renderer = require('vue-server-renderer').createRenderer(); //第三步,将vue渲染为HTML renderer.renderToString(app, (err, html)=>{ if(err){ throw err; } console.log(html); });
保存以上代码后,在 vue-ssr-demo 文件夹下打开命令行工具,执行 node server.js 命令,可获得以下 HTML 内容:api
➜ vue-ssr-demo node server.js
<div data-server-rendered="true">hello world</div>
好,上面的例子中咱们已经让 vue 在服务端,也就是 node 环境下运行起来了,到这里其实已经实现了 vue 的服务端渲染了。
但是,实际项目中使用哪有这么简单,起码数据还没渲染啊,那接下来咱们看看如何渲染数据:
vue-ssr 渲染数据的方式有两种,咱们先看下第一种:
// server.js const data_vue = { word: 'Hello World!' }; //第一步,建立vue实例 const Vue = require('vue'); //vue 实例化过程当中插入数据 const app = new Vue({ data: data_vue, template: "<div>{{word}}</div>" }); //第二步,建立一个renderer const renderer = require('vue-server-renderer').createRenderer(); //第三步,将vue渲染为HTML renderer.renderToString(app, (err, html)=>{ if(err){ throw err; } console.log(html); });
第一种方式,在建立 vue 实例时,将须要的数据传入 vue 的模板,使用方法与客户端 vue 同样;运行 server.js 结果以下,数据 data_vue 已经插入到 vue 模板里面了:
➜ vue-ssr-demo node server.js <div data-server-rendered="true">Hello World!</div>
第二种,模板插值,这里咱们也直接先放代码:
const data_vue = { word: 'Hello World!' }; const data_tpl = { people: 'Hello People!' }; //第一步,建立vue实例 const Vue = require('vue'); const app = new Vue({ data: data_vue, template: "<div>{{word}}</div>" }); //第二步,建立一个 renderer 实例 const renderer = require('vue-server-renderer').createRenderer({ template: "<!--vue-ssr-outlet--><div>{{people}}</div>" }); //第三步,将vue渲染为HTML renderer.renderToString(app, data_tpl, (err, html)=>{ if(err){ throw err; } console.log(html); });
这里咱们增长了数据 data_tpl,你会发现,在 renderToString 方法中传入了这个参数,那么这个参数做用在哪里呢?这就要看下官网中关于 createRenderer 和 renderToString 方法的介绍了,
createRenderer: 使用(可选的)选项建立一个 Renderer 实例。
const { createRenderer } = require('vue-server-renderer')
const renderer = createRenderer({ / 选项 / })
在选项中,就有一个参数叫 template,看官网怎么说的:
template: 为整个页面的 HTML 提供一个模板。此模板应包含注释 <!--vue-ssr-outlet-->,做为渲染应用程序内容的占位符。为整个页面的 HTML 提供一个模板。此模板应包含注释 <!--vue-ssr-outlet-->,做为渲染应用程序内容的占位符。
模板还支持使用渲染上下文 (render context) 进行基本插值:
使用双花括号 (double-mustache) 进行 HTML 转义插值 (HTML-escaped interpolation);
使用三花括号 (triple-mustache) 进行 HTML 不转义插值 (non-HTML-escaped interpolation)。
根据介绍,在建立 renderer 实例时,能够经过 template 参数声明一个模板,这个模板用来干吗呢?就用来挂载 vue 模板渲染完成以后生成的 HTML。这里要注意一下,当建立 renderer 实例时没有声明 template 参数,那么默认渲染完就是 vue 模板生成的 HTML;当建立 renderer 实例时声明了 template 参数,必定要在模板中增长一句注释 “<!--vue-ssr-outlet-->” 做为 vue 模板插入的占位符,不然会报找不到插入模板位置的错误。
再次运行 server.js ,结果以下,vue 模板已成功插入,且 template 模板中的 {{people}} 变量也因在 renderToString 方法中第二位参数的传入,显示了数据:
➜ vue-ssr-demo node server.js <div data-server-rendered="true">Hello World!</div><div>Hello People!</div>
若是咱们把 template 换成一个 HTML 页面的基本架构,来包裹 vue 模板,是否是就能获得一个完整页面了呢?咱们来试一下:
const data_vue = { word: 'Hello World!' }; const data_tpl = { people: 'Hello People!' }; //第一步,建立vue实例 const Vue = require('vue'); const app = new Vue({ data: data_vue, template: "<div>{{word}}</div>" }); //第二步,建立一个renderer const renderer = require('vue-server-renderer').createRenderer({ template: `<!DOCTYPE html> <html lang="en"> <head><title>Hello</title></head> <body> <!--vue-ssr-outlet--><div>{{people}}</div> </body> </html>` }); //第三步,将vue渲染为HTML renderer.renderToString(app, data_tpl, (err, html)=>{ if(err){ throw err; } console.log(html); });
运行 server.js ,结果以下,咱们获得了一个完整的 HTML 页面,且成功插入了数据:
➜ vue-ssr-demo node server.js <!DOCTYPE html> <html lang="en"> <head><title>Hello</title></head> <body> <div data-server-rendered="true">Hello World!</div><div>Hello People!</div> </body> </html>
好,如今页面生成了,该怎么显示呢?这里咱们借助下框架 Koa 实现,先来安装:
npm install koa -S
而后修改 server.js ,以下:
const data_vue = { word: 'Hello World!' }; const data_tpl = { people: 'Hello People!' }; const Koa = require('koa'); //建立 koa 实例 const koa = new Koa(); const Vue = require('vue'); //建立一个renderer const renderer = require('vue-server-renderer').createRenderer({ template: `<!DOCTYPE html> <html lang="en"> <head><title>Hello</title></head> <body> <!--vue-ssr-outlet--><div>{{people}}</div> </body> </html>` }); // 对于任何请求,app将调用该异步函数处理请求: koa.use(async (ctx, next) => { // await next(); //建立vue实例 const app = new Vue({ data: data_vue, template: "<div>{{word}}</div>" }); //将vue渲染为HTML const body = await renderer.renderToString(app, data_tpl); ctx.body = body; }); // 在端口3001监听: koa.listen(3001); console.log('app started at port 3001...');
运行 server.js :
➜ vue-ssr-demo node server.js app started at port 3001...
而后打开浏览器,输入网址 http://localhost:3001/ ,便可看到运行后的效果。
这样就实现了一个简单的服务端渲染项目,可是咱们在日常开发的时候,确定不会这么简单的去构建一个项目,必然会用到一些,好比打包、压缩的工具,这篇就写到这里,下一篇咱们尝试使用 webpack 来构建一个 vue 的服务端渲染项目。
若有问题,欢迎指正!谢谢!