雅虎前端优化14条军规——HTML5游戏实践

Published: 2016-09-24 Category: 技术

14条让网站加速的“黄金法则”

赫赫有名的雅虎前端优化14条军规其实早在2007年就被雅虎首席性能工程师Steve Souders总结成书并由著名的计算机书籍出版商O'Reilly出版——《High Performance Web Sites》(中译版《高性能网站建设指南》则是在2008年由电子工业出版社出版),这里记录下自己在真实的线上项目中如何根据情况去实施这些军规,即作为个人总结也作抛砖引玉之用

book

该书揭露了Web前端加载缓慢的罪魁祸首是——浏览器对HTML文件内Web组件的下载与解析:即浏览器对Web站点的HTML文件进行HTTP请求后(无缓存情况下),服务器响应HTML文件的时间只占总响应时间的10%~20%,而其余的80%~90%响应等待时间则花费在对HTML文件内Web组件的下载(HTTP请求)和解析(JavaScrip、CSS、图片的下载以及DOM的解析生成等)!

即所谓的网站性能黄金法则

只有10%~20%的最终用户响应时间花在了下载HTML文档上,其余的80%~90%时间花在了下载和解析页面中的所有组件上

所以,请先不遗余力的去优化前端(减少那80%~90%的组件下载解析时间),更主要的是这14条军规的实施相较优化后端(重构代码架构或者数据库结构)来说更简单,而且都是经过多年和许多网站实践验证可行的,实施后立竿见影和事半功倍!

项目简介和14条军规的实践

项目简介

我们的项目是一款养成经营模拟类的HTML5游戏——《QQ花藤》,即使不是传统的Web互联网网站,但是HTML5游戏本质上也还是网页游戏,即通过JavaScript脚本在浏览器中运行的游戏。其实只要本质上是涉及到浏览器访问Web页面,且需要下载和解析Web页面内的组件,那这14条网站加速的“黄金法则”都是适用的!

game

下面就针对这14条军规在项目中的实践做下阐述和总结

规则1:减少HTTP请求

这是最最最重要的一条!根据前面提到的网站性能黄金法则我们知道,网页80%~90%的响应时间都花费在浏览器下载和解析Web页面组件了,所以减少Web组件的数量以此来减少浏览器进行HTTP请求下载和解析的工作量,会让浏览器更迅速的打开Web页面

在我们的H5游戏项目中,减少HTTP请求这个规则主要针对的是图片资源的合并和JavaScript脚本代码的合并,即使用图片合成工具,将一些零碎的小图合成一张大图——雪碧图,如此一来只需要一次HTTP请求即可

pic01

而针对JavaScript脚本的合并,因为目前H5游戏前端无论哪个流行框架(Cocos2d-JS白鹭或者LayaBox),都会集成发布H5游戏页面index.html的功能,其中就会把开发者们编写的JavaScript(即使真正开发者使用的不是原生的JavaScript语言,例如C++、TypeScript或者ActionScript,也能自动转换为JavaScript代码)代码压缩合并成app.min.js(注意下面截图为app.max.js只是名字为max而且,其实代码是已经经过压缩和精简后的),同样也只需要一次HTTP请求就能获取所有前端业务逻辑的源代码了

pic02

在H5游戏项目上线后,我们前后端一起监控查看进入游戏的HTTP请求细节,详细分析可以针对哪些个HTTP请求进行延后请求或直接合并成为一条HTTP请求内容中,在这个优化过程中减少了20+左右的HTTP请求

规则2:使用CDN(内容分发网络)

CDN的好处是建立在如下这一事实的基础上的:用户从浏览器发出去的HTTP请求最终还是需要通过层层网络的路由查找才能到达目标服务器并从服务器获取所需要的资源,该过程中就存在了由往返服务器距离的长短来决定响应时间的长短——所以当然是距离用户越近就越快!

而CDN的主要作用就是尽量把资源同步到离用户最近的网络服务器上以此来缩短网络路由的查找,并最终达到加快HTTP资源响应的时间

pic03

在我们的H5游戏中,我们把前端资源放置在腾讯云平台的CDN上,目的就是为了提高用户访问前端资源的响应速度。但这里注意一下腾讯云平台的CDN提供了2种接入方式:

  1. COS源
  2. 自有源

下面简述下2种方式的异同和选择

腾讯云CDN——接入COS源

腾讯云COS源前端资源的上传需要先下载配置腾讯云平台提供的Python脚本,然后配置一些密钥和上传目录等等信息,最后执行Python脚本来完成上传;然后通过腾讯云平台还可以设置CDN的HTTP头信息:

pic04

但是COS源有2个最致命的缺点:

1、除了上图指定的HTTP响应头外不能自定义其他的HTTP响应头;

2、针对JavaScript脚本文件其HTTP头的Content-Type为application/octet-stream

这2条缺点会直接导致 规则3:添加Expires(缓存过期)头规则4:压缩(Gzip)组件 不能实施!所以最终我们不得不切换到自有源的方式下

腾讯云CDN——接入自有源

腾讯云自有源的工作方式给了使用者最大化的控制权:即可以配置自有源的源站地址为腾讯云上的一台单独的CVM机器,只要该CVM机器提供HTTP访问服务即可(这里我们使用Nginx来提供HTTP服务),之后对于CDN的首次访问——即回源访问都会先到这台CVM机器上进行请求,然后再自动同步到其他CDN节点上

所以这台CVM机器就是代表源站CDN服务器,然后我们可以利用这台CDN服务器配实施 规则3:添加Expires(缓存过期)头规则4:压缩(Gzip)组件 ——即对各种HTTP响应头进行配置

而又因为我们拥有对该CDN服务器的控制权,上传部署最新的前端就可以先在我们的内网机器上从SVN下载最新的前端资源,然后使用rsync或者scp命令同步更新到CDN服务器即可,最后可以使用腾讯云平台的“缓存刷新”来把源站CDN服务器的资源同步到CDN节点上,避免了回源访问从而减少了源站CDN服务器的负载

pic05

最终也验证了使用CDN确实更快一些,当然后续的一些规则例如前面一直提到的规则3和4,配合上CDN来实施最终发挥到了预期的最优效果

规则3:添加Expires(缓存过期)头

规则4:压缩(Gzip)组件

规则5:将CSS样式表放在顶部

由于浏览器的逐步呈现的渲染机制——为了避免当CSS样式变化所带来的重绘元素开销,把CSS样式放在顶部有助于避免浏览器阻塞样式渲染导致的“白屏”的现象

我们的QQ花藤H5项目由于是在移动端的游戏,所以其实并没有所谓的页面DOM元素的呈现渲染,因为所有的游戏元素都是采用Canvas或者WebGL绘制的,所以此规则在H5项目就可以省略了

但是我们QQ花藤还有PC端的QQ空间版本,该版本需要编写CSS样式文件以适配QQ空间的iframe,所以在PC版我们就可以使用此规则了

pic06

这里直接在页面中写死了CSS样式,按照 规则8:使用外部JavaScript和CSS,应该写成link外部CSS的方式并把该CSS放到CDN,这里我们算是偷了个小懒吧

规则6:将JavaScript脚本放在底部

由于JavaScript脚本阻塞了浏览器并行下载——因为浏览器不敢确保脚本是否会使用document.write修改页面的内容,所以浏览器会选择等待脚本下载完成来确保页面的恰当布局

正以为如此,对位于该JavaScript脚本以下的内容(尤其是存在CSS样式的话)越多,则浏览器的逐步呈现渲染机制就会被阻塞的越晚。这就是为什么我们需要尽量把JavaScript放在底部的原因

这条规则的遵循还是比较容易的,我们的H5和PC版的QQ花藤都直接把引入JavaScript脚本放到了最底部

pic07

pic08

规则7:避免CSS表达式

由于H5游戏项目的元素都是采用Canvas或者WebGL绘制的,有些连CSS样式表都省略了,所以此条规则也可以忽略了

规则8:使用外部JavaScript和CSS

从上述 规则5:将CSS样式表放在顶部规则6:将JavaScript脚本放在底部 所贴出的H5项目截图,JavaScript脚本基本都使用引入的方式了,有些没有做到确实也是因为偷懒了

规则9:减少DNS查找

规则10:精简JavaScript

规则11:避免重定向

规则12:移除重复JavaScript脚本

规则13:可选择的配置ETag

规则14:可选择缓存Ajax请求

参考

(未完待续。。。)

  • 版权声明:自由转载-非商用-非衍生-保持署名 | BY-NC-SA
  • 文章作者:「whg」
  • 发表日期:2016年09月24日