本文选自《当代前端技能解析》。
SPA场景下SEO的问题常日情形下,SPA运用或前后端分离的开拓模式下页面加载的基本流程是,浏览器端先加载一个空页面和JavaScript脚本,然后异步要求接口获取数据,渲染页面数据内容后展示给用户。那么问题来了,搜索引擎抓取页面解析该页面HTML中关键字、描述或其他内容时,JavaScript尚未调用实行,搜索引擎获取到的仅仅是一个空页面,以是无法获取页面上中的详细内容,这就比较影响搜索引擎收录页面的内容排行了。只管我们会在空页面的里面添加keyword和description的内容,但这肯定是不足的,由于页面关键性的正文内容描述并没有被搜索引擎获取到。
如果利用Node后端数据渲染(有人称之为直出,后文中也称之为直出层),在页面要求时将内容渲染到页面上输出,那么搜索引擎获取到的HTML就已经包含页面完全的内容,页面也就更随意马虎被检索到了。

除了SEO问题,在前后端分离的开拓模式下页面在JavaScript实行渲染之前是空缺的(或提示用户加载中)。如图6-3所示,用户在看到数据时已经花费的网络等待韶光:DOM***韶光 + DOM解析韶光 + JavaScript文件要求韶光 + JavaScript部分实行韶光 + 接口要求韶光 + DOM渲染韶光。这时用户看到页面数据时已经是三次串行网络资源要求之后的事情了。
前后端分离办法页面渲染紧张流程
然而,如果利用后端直出来进行数据渲染,首先SEO的问题不复存在,用户浏览器加载完DOM的内容解析后即可立即展示,网络加载的问题也得到办理。其他的逻辑操作(如事宜绑定和滚动加载的内容)则可按需、按异步加载,从而大幅度减少展示页面内容花费的韶光。那么一样平常Node后端数据渲染的全体流程又是若何的呢?
图6-4为目前一样平常后台页面数据直出的通用架构设计,直出层接管前真个路由要求,并在Node真个Controller层异步要求做事接入层接口,得到Model数据并进行组装拼接,然后提取相对应的Node端View模板渲染出HTML输出给用户浏览器,而不用通过前端JavaScript要求动态数据后渲染。不仅如此,直出层根据不同的浏览器userAgent,也可以提取不同的模板渲染页面返回给不同的用户浏览器,以是这种实现办法不仅非常适宜大型运用做事的实现场景,而且可以方便地实现网站的相应式内容直出。
Node直出层开拓Web架构
avalon2的后端渲染实践
avalon2为了提高性能,采取全新的架构,四层架构,个中一层为虚拟DOM。
虚拟DOM的一个好处是能大大提高性能,另一个好处是能差错整描述我们的页面构造。因此在非浏览器环境下,虚拟DOM也能正常运行。并且avalon2自一开始,就努力隔离DOM API。基于这两点,avalon2可以原封不动地运行于nodejs中,进行定义VM,渲染视图等操作。
客户端上,虚拟DOM通过vm.$render
方法渲染到页面中
做事端上,虚拟DOM利用serveRender
天生HTML字符串
与react的后端渲染比较,它的利用是非常大略的。React的渲染单位是组件,组件有生命周期,我们在添加一些处理时,都是放在生命周期钩子中(getDefaultProps,getInitialState,componentWillMount,componentDidMount,componentWillUpdate。。。。),而在nodejs,生命周期只能走到componentDidMount之前。用户想后端渲染,须要有针对性地写代码。而avalon2则不须要懂这些,只要担保所有DOM操作在回调中就行了。
react的后端渲染有两个方法,ReactDOMServer.renderToString 和 ReactDOMServer.renderToStaticMarkup。renderToString带着uuid,为了前端只进行绑定事宜,不再天生DOM,但缺陷是让页面体积变大很多。而renderToStaticMarkup只能输入不带交互的静态页面。
而avalon只有一个方法,它输出的页面没有ms-xxx,:xxx这些绑定属性,因此相称于输出静态页面。为了实现绑定属性功能,如果将模板函数或已经天生好的事宜传过去,想必体积太大。因此avalon将原始页面的很少一部分压缩传过去。即便你没有用html-minify这些工具,avalon也会做去空缺节点处理!
因此从天生页面速率,与传输体积上,avalon的后端渲染都比react精良不少。
与传统后端渲染比较,即JSP,PHP方案,紧张好处是,模板的掌握台节制在我们前端手中。不要痛楚成为套页面的工具。avalon对切图职员交给我们的页面,所做修恰是很少的,便是加一些绑定属性。
与近年盛行前端模板渲染方案比较,即后端出数据,前端在script标签,textarea标签里写模板,紧张好处是SEO!
前端模板是无法搞定SEO,并且还有\"大众首屏乱码\"大众问题,这些在ng, avalon1, vue1 也有这问题,须要ng-cloak 等东西做遮丑布!
有了后端渲染就没有这问题了。
好了,我们看如何做。为大略起见,本文利用koa2做后端框架。koa2是利用es7的async function处理异步,从此告别异步地狱与那些深涩难懂的generators。
但就算最新的nodejs6也不支持async function,不过没紧要,我们可以利用babel。至于如何用,后面直接给出一个例子。现在我们看一下一些通用的步骤,熟习了它,你可以将avalon用于koa1, express及其他nodejs框架。
引入最新版 avalon 这里用avalon.modern体积少些
引入avalon仓库下的serve下的文件serveRender.js
引入你定义VM的文件 (所有DOM操作要在回调里进行,不要涌现 window, document, 方便能在nodejs环境中运行) 对你的VM利用webpack进行打包 (目的是处理module.exports, require)
var vm = avalon.define({ $id: \公众test\公众, aaa: '222'})module.exports = vm //这里必须利用module.exports,而不是es6 module
引入你该页面的模板(便是一个普通的HTML文件片段,里面须要用ms-controller,指向你刚才的VM.$id)
将VM与模板放进serveRender方法,得到一个工具,里面包含渲染好的HTML(A) 及 一个包括所有模板的工具(B)
创建一个script标签, 里面定义一个avalon.serverTemplates工具, 将B工具赋给它
将上面的标签与A页面, 赋给ctx.body发往前端(或其他可以放送到前真个方法里面去)
//1. 引入avalonvar vm = require('./src/avalon')//2. 引入avalon的后端渲染器var serveRender = require('./dist/serverRender')//3. 当前页面VMvar vm = require('./src/vm')//4. 当前页面模板var test = fs.readFileSync('./src/aaa.html', 'utf-8');//5.
这些我已经做成一个例子,放到GITHUB中,大家可以下回来看。
这是后端返回前真个源码,大家可以做得更俊秀些,把head, body, html等标签补上。不过就算你不写,浏览器也会帮你补上的。
这是效果图!
有了后端渲染,我们就可以加快首屏的渲染速率与SEO。 并且我们可以实现前后同构, 前后端共用一套模型(VM),一套验证代码,一套模板!
!
!
做ABTest,埋点等也测试了!
后真个一些部分也节制在我们前端手中,我们的代价就越来越大,人为自然也上去了!
有关后端渲染的话题,大家也可以看一下react的方案及早期百度,腾讯基于它们的私有框架的实践。