1

目前,为了加快网站手机端网页首屏渲染速度,提高在网速较慢的国家地区的用户体验,提高在谷歌测速网站的评分,同时为了以后seo需求做准备,需要对网站手机端的各个页面进行优化。而网站的后台基于php框架开发,手机站则使用了vue.js作为了前端框架,因此首屏渲染方案需要同时考虑到前后端php与vue两个部分以及交互问题。

什么是“直入直出”

直入直出其实就是指的ssr(server side render)服务器端渲染,由服务器端渲染出静态页面,直接返回给客户端,然后客户端去激活这些静态页面,让这个页面变成可以交互的,并且能够影响到后续的数据变化响应。

方案调研

​ vue首屏优化方案主要有主流的vue ssr(server side render)服务器端渲染和前后端同构等方案。

Vue SSR

vue ssr采用服务器端渲染,前端获取数据进行激活的形式,这种形式目前适用于前后端分离的项目,并且需要在服务器部署前端机器,优点是便于做seo需求,页面加载速度快,缺点是会增加部分服务器开销。

前后端同构

前后端同构,主要是选择一种前后端都支持的一种模板语言(例如php-v8js与mustache.php等)进行同构处理的形式,不同项目不尽相同。

​ 而结合目前网站的项目结构,采用前后端分离的vue ssr模式以及前后端同构的形式似乎对网站项目结构不太适用,因此从这两种模式中总结出最适合最契合网站项目的形式才是比较合适的。

方案分析

目前网站渲染流程

​ pc端:php处理数据 -> 渲染数据到模板 -> 展示htm到浏览器 -> 加载js等数据 -> js更改某些数据或样式。

​ m手机端:php处理数据 -> 渲染数据到模板 -> 展示htm到浏览器(空白) -> 加载js等数据 -> vue.js构建并挂载到dom节点。

期望网站渲染流程

​ m手机端:php处理数据 -> 渲染数据到模板 -> 展示htm到浏览器(首屏数据) -> 加载js等数据 -> vue.js构建并挂载到htm(激活)。

类似于前后端同构的思想,我们需要一个中间桥接模板去连接php与vue做首屏渲染方案,理想中的状态是由php直接渲染不需要大量交互的结构内容到模板里,然后客户端在获取到html时,可以直接展示出静态的不需要交互的页面内容,此时客户端再去加载js文件,加载完后直接激活页面上需要交互的模块与数据。

因此采用服务器端首次渲染,前端二次渲染的模式,服务器端渲染简单页面元素、不需要大量交互的原vue组件以及前端所需的数据这样的方案似乎更接近网站目前已有结构所能支持的方案。

当然,以上只是针对于网站项目结构所做的一些设想,针对于不同的网站项目结构在不做网站项目重构的前提下应该选择最适合当前网站的方案。

基于以上设想,在正式采用方案之前,似乎还应该再去注意下vue渲染的生命周期,说不定能找到一些新的突破口。vue生命周期如下:(vue生命周期详解
vue生命周期.png
可以注意到的是在created和mounted之间似乎有我们想要关注的重点:

1. 在created的阶段,如果vue实例对象中有template参数选项,则将其作为模板编译成render函数。如果没有template选项,则将外部HTML作为模板编译。可以看到template中的模板优先级要高于outer HTML的优先级。这就意味着我们似乎在编译vue时可以使用外部的html进行渲染,与我们之前的想法不谋而合,我们可以在php中进行第一次渲染然后再将html返回给客户端进行第二次渲染。
clipboard.png
2. 在beforeMounted阶段,可以看到此时是给vue实例对象添加$el成员,并且替换掉挂在的DOM元素。因为在之前console中打印的结果可以看到beforeMount之前el上还是undefined。这似乎意味着在js为正式加载完成之前,我们可以在空白页面上搞点事情,让首屏页面不至于为空白,反正当js加载完毕,el将挂载在根节点上面,似乎也是可以让体验有所提升的。
clipboard.png

方案可行性

经过以上对vue生命周期的分析,针对网站结构得出两个似乎可行的方案,分别是混合式渲染方案(php渲染第一次渲染,vue第二次渲染),首屏替换方案(首屏直接通过html展示,由vue.js加载完成直接替换)

混合式渲染方案

添加编译器到前端渲染,这里需要一下注意运行时(runtime)与编译器(compiler )的区别与运用,采用前端编译,即template不再在webpack打包时生成,而是在前端根据后端已渲染后的模板再次进行二次编译渲染。如此一来js文件体积将比只采用运行时的版本大30%左右。

1567589762(1).png

这样处理的方式有利有弊,有利的地方在与可以加快首屏渲染,减少白屏,便于做手机站seo需求,提升用户体验,特别是针对网速较慢的用户;弊处在于部分组件template将于js代码产生分离,代码可读性将降低,可能增加js体积。因此选用此种方案的组件或模块需要反复斟酌,慎重抉择。可选择将部分不涉及重要或复杂逻辑的页面运用此种方案。

1567589651(1).png

一些注意事项

  1. vue进行template时对dom中的htm敏感,因此书写变得稍显严格,如v-if等vue语法,都需用<template v-if>xxx</template>的形式包裹,props参数及emit函数需用横线连接,如:bannerHeight写为:banner-height, @acceptUseCookie改写为@accepct-use-cookie等。
  2. 组件嵌套template写法如<main><banner></banner></main>的形式,可灵活采用twig模板语法中的include引入功能,extend继承功能以及block结合的形式进行改写。
  3. 因为首屏渲染的内容可能包含许多组件内的内容,因此需要放开组件里的template内容到主组件的template内容里,将组件里的template写在后端模板中,如此一来,实则将组件融合到了主组件中,弱化了组件的概念。对于组件生命周期里的钩子在主组件采用mixin的形式引入组件,data,created,mounted等钩子将自动merge到主组件的钩子中,因此尽量使子组件中的data中的元素以及method中的函数不与主组件中的产生命名冲突,如果子组件有props参数可删去这些参数但组件中使用的的props参数需与主组件中的命名保持一致(可注明传入了哪些参数),便于了解这些参数来自主组件。处理子组件与父组件之间的关系时需细心谨慎。
  4. 子组件style less文件去掉scoped参数,将less按层级书写规范。
  5. 组件是否参与首屏渲染需仔细考虑,建议将结构简单没有复杂交互逻辑的组件进行首屏渲染,如首页banner与slogan等相对比较主观的元素采用首屏渲染在体验上会更好。若某些父组件中的子组件需要先于父组件mounted以完成某些特殊逻辑,则不建议采用此种做法。
首屏替换方案

在js未加载完成前,首屏页面由后端直接渲染通过html返回,等js加载完成后vue的el直接替换首屏页面接管前端页面。


云清扬
4 声望0 粉丝