最近做了报名页的第三期,就顺手对该项目进行了一些优化。先看h5报名页优化前后性能的对比吧:
。
优化前首屏的秒出率大概是30%左右,优化后的首屏秒出率大概是70%左右。ps:因为主要是对个人想法的一些验证,所以没并没有使用客户端的use304cache和龙哥做的service worker缓存。
项目背景
该页面位于虎牙直播,虎牙助手,虎牙手游的活动中心中。由 运营同学在管理后台配置所需要的表单字段(单选,多选,输入框,多行文本框,上传图片等),生成对应的报名表单。用户填写表单报名。该项目的优化基于龙哥开发的脚手架。
其实加快首屏时间有两个关键词,一个是加载,一个是渲染。加快首屏时间就是要减少渲染首屏所需的文件数量和文件尺寸和尽早执行首屏渲染的逻辑。下文所讲述的方法也是围绕着这两点。
精简代码
emmmm ... 这个好像是句废话,不过却相当重要,移动端的网络条件较差,文件大小对加载速度还是十分有影响的。 尤其是css, 改造旧项目的时候,光冗余的css就删除了将近300行。举几个栗子:
了解元素的默认属性,比如块级元素不用再设置 width:100%
设置了绝对定位,浮动的内联元素不用再设置 display:block
注意样式的继承关系,像 文本相关属性(颜色, 字体种类,缩进,行高等)列表相关属性(list-style)等可以继承的属性,在父级元素设置了之后,子元素就不用重复设置该属性了
另外还包括简化 dom结构,减少元素间嵌套。
首屏css内联
移动端一个不可忽略的事实是 移动端的文件的缓存命中率比较低。css文件一般在head标签里进行引入,外链的css文件会阻塞HTML页面渲染,HTML页面会被继续下载,阻塞点后面的标签会继续被解析,img,link等会继续发送请求获取外部资源,但不会合成Rendering Tree或不会触发页面渲染,也不会执行JavaScript代码。因为使用fis3进行构建,在css文件后面加上?__inline即可。
<link rel='stylesheet' href='index.scss?__inline'>
异步加载非首屏模块
在本项目中, 非首屏的模块我划分出来了两个。 一个是报名成功后的状态展示。如下图
报名成功后状态
一个是表单校验逻辑 模块。
上述两个模块均可以在渲染完表单之后再进行加载。这个时候有的同学说了,报名成功状态异步加载我没意见,但是表单检验模块你异步加载,万一用户在该模块还未加载完成的时候就点击提交开始进行校验,那岂不是要报错了吗。
莫慌,那就把这部分用户考虑进去,伪代码如下:
var valiator;function loadValiatorMod(cb) { require.async('valiator.js', (mod)=> { valiator = mod; cb && cb(); }) } loadValiatorMod(); $saveInfo.on('click', ()=> { if(!valiator) { loadValiatorMod(()=>{ valiator.start(); // 提交表单 }) }else{ valiator.start(); // 提交表单 } })
一开始就让
按需加载
如上所说,该项目要同时适配虎牙直播和助手手游APP,那么可以去根据不同的平台去加载一些特性代码。伪代码如下:
var isAnchorApp = util.getUrlParam('isAnchorApp') === 1; // 是否是开播app if(isAnchorApp ){ loadJs('huyasdk.js', function() { writeCookie(); }) }else{ loadJs('anchorApp.js'); }
报名表中可能有上传图片的操作,上传图片的需要之前升泽写的一个插件,但是不是每一个报名表所必须的,当有上传图片的表单再去加载这个插件
renderFirstScreen(); // 在渲染逻辑执行完之后再判断是否加载上传组件 var needUploadImg = $('.upload-img').length > 0; needUploadImg && loadJs('upload.js');
其他常规操作(不具备通用性)
jquery版本由1.8版本升级到2.x版本,包体积减小
去除引入es6的polyfill文件,龙哥帮忙改造了构建工具,可以对es6的一些新特性的进行针对性的polyfill。
延迟加载。 对性能上报js做了延迟加载的处理
上了https。
在优化本项目的时候,发现由客户端同学维护的js sdk并没有做gzip压缩。 让运维同学帮忙处理之后,js sdk的大小由17kb减少至了6kb。
其实,还可以有其他方面可以做,等下次报名页优化的时候再做吧~:
首屏关键js内联
这个我们要对现有的js代码进行拆分,使得拆分后首屏的js只包括如下三个部分的代码:
请求相关,渲染相关,控制非首屏模块加载逻辑。node中间层
理论上也是可行的。在前端这边把请求相关和渲染相关的js单独拎出来。在node 这边使用node试用 ajax库和模板引擎进行替换,拼接好html和内联的css和 请求,渲染相关的js后,一起返回。公用库替换
纵观现在组里的h5项目,复杂一些的项目还是比较少的。依据之前的经验,其实我们使用jquery/zepto的话,使用频率最高的功能是 ajax, selector, event 这三个。 其实可以把这些模块给封装在一起,而不是全部使用。
当然,纸上得来终觉浅,上述的几个方案还是要自己去试,有数据支撑后才能证明方案的正确性和可实施性。
总结
优化之后发现其实优化手段没有那么复杂,再简单的项目也有优化空间,得益于构建工具,性能上报等这些基础设施的完备,才能更好的对项目进行优化。下篇文章以上电视主播设置h5聊聊单页面应用的优化~
参考文章: http://www.cnblogs.com/fsjohnhuang/p/6739064.html
www.alloyteam.com/2015/10/optimization-of-alloyteam-series-the-first-screen-time/
作者:浴火小青春
链接:https://www.jianshu.com/p/c2d19b95b004