前言:性能黄金法则揭示了只有10%~20%的最终用户响应时间是花在从Web服务器获取HTML文档并传达到浏览器中的,剩下的80%~90%时间花在为html文档所引用的所有组件(图片、脚本、样式表、Flash等)进行的http请求上。如果希望能够有效地减少页面的响应时间,就必须关注剩余80%~90%的最终用户体验。那么这80%~90%的时间花在哪里了?如何减少它?下面将从高性能网站建设指南总结(14条规则)来介绍如何优化加速页面的响应,最终提升用户体验。
时间花在哪了?
- 至少80%的最终用户响应时间花在了页面的组件上
- 有缓存的场景并没有太多下载活动,但紧跟在html文档的http请求之后会有一段空白时间,没有进行下载。但在这段时间里,浏览器正在解析html、JavaScript和css,并从缓存中获取组件
- 大量的http请求并行发生
- 在请求脚本时不会发生并行请求。这是因为在很多情况下,浏览器在下载脚本时会阻碍额外的http请求
测试结果表明:其实时间没有花在下载html文档上,包括任何的后端处理。
(PS:以上为《高性能网站建设指南》一书中的实验结论)
遵循的规则:
规则1: 减少http请求
(1). 图片地图
(2). CSS Sprites(雪碧图/精灵图)、Iconfont
通过把多个图片合并到一个图片,然后利用background-position进行定位,比使用分离图片快50%。或者用Iconfont、Base64等技术来代替小图标的图片
(2). 内联图片
使用data:URL的模式在web页面中包含图片,但无需任何额外的http请求
格式: data:[<mediatype>][;base64],<data>
举个例子
<img alt="要显示的图片" src="data:image/gif;base64,R0lGODlhAQAcALMAAMXh96HR97XZ98Hf98Xg97DX97nb98Lf97vc98Tg973d96rU97ba97%2Fe96XS9wAAACH5BAAAAAAALAAAAAABABwAAAQVMLhVBDNItXESAURyDI2CGIxQLE4EADs%3D);">
或
.gift { background-image:url(data:image/gif;base64,R0lGODlhAQAcALMAAMXh96HR97XZ98Hf98Xg97DX97nb98Lf97vc98Tg973d96rU97ba97%2Fe96XS9wAAACH5BAAAAAAALAAAAAABABwAAAQVMLhVBDNItXESAURyDI2CGIxQLE4EADs%3D); background-repeat:repeat-x; }
(3). 合并脚本和样式表
每个文件都会导致一个额外的http请求,好的网站的脚本和样式表一般不超过2个
使用模块化工具,比如sea.js , require.js 进行优化,不然随着文件的增多,手动合并将会很麻烦
规则2: 使用内容分发网络(content delivery network) CDN
规则3: 添加Expires头
规则4: 压缩组件
主要是压缩脚本和样式表
压缩的成本:服务器端会花费额外的CPU周期来完成压缩,客户端要对压缩文件进行解压缩
gzip是典型的压缩选择
从http1.1开始,web客户端可以通过请求中的Accept-Encoding头来表示对文件压缩的支持.
---> Accept-Encoding:gzip 如果web服务器看到请求中有这个头,就会使用客户端列出来的方法中的一种来压缩响应, 并通过响应中的Content-Encoding来通知客户端..
<--- Content-Encoding:gzip Gzip是目前最有效,最流行的压缩方法,免费模式,并被标准化为RFC 1952.(90%) 具体可搜mod_gzip的网站参考
规则5: 将样式表放在顶部
使用link标签将样式表放在文档head中,可以避免无样式内容闪烁
规则6: 将脚本放在底部
如果将脚本放在顶部,脚本会阻塞对其后面内容的呈现和下载,直到脚本加载完毕
详细解释:js文件是用src嵌入的,src用于指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;在请求src资源时会将其指向的资源下载并应用到文档内。
当浏览器解析到src元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等元素也是如此,这就是为什么将js脚本放在底部而不是头部的原因。
规则7: 避免使用css表达式.
应避开css表达式. 可以用事件处理器来为特定的事件提供所期望的动态行为
规则8: 使用外部的JavaScript和css
内联只有一个http请求, 但内联无法缓存, 外置可以缓存, 而且组件重用, 缓存优势更明显.
规则9: 减少DNS查找
如何减少? --> 减少唯一主机名的数量就可以减少DNS查找的数量。使用较少的域名,谷歌(http://www.google.com)只有一个,它的页面只需要一次DNS查找。 因为只有两个组件,可以一次并行下载完, 两个主机名是最好的,不要超过4个,平衡并行下载和DNS查询
DNS缓存和TTL
规则10: 精简JavaScript
精简: 是从代码中移除不必要的字符以减小其大小,进而改善加载时间的实践.
代码精简之后所有的注释以及不必要的空白字符(空格,换行,制表符),可以减少20%
混淆: 精简后还会把函数和变量的名字转换为更短的字符串
精简css
优化css-->合并相同的类,移除不使用的类等.
规则11: 避免重定向
重定向(Redirect)用于将用户从一个URL重新路由到另一个URL。重定向有很多种,301和302是最常用的两种。重定向会使你的页面变慢,在用户和html文档之间插入重定向延迟了页面中的所有东西。
规则12: 移除重复脚本
在一个页面中两次包含同一个JavaScript文件会损伤性能
规则13: 配置或移除ETag
规则14: 使Ajax可缓存
推荐测试工具:Firebug 能够调试JavaScript代码,检查DOM、调整CSS、执行JavaScript和浏览页面HTML等功能
web 性能优化方案:
1、尽量减少 HTTP 请求
2、使用浏览器缓存
3、使用压缩组件
4、图片、JS的预载入
5、将脚本放在底部
6、将样式文件放在页面顶部
7、使用外部的JS和CSS
8、精简代码
前端开发的优化问题(详情可以看雅虎14条性能优化原则):
(1) 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存 ,图片服务器。
(2) 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
(3) 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
(4) 当需要设置的样式很多时设置className而不是直接操作style。
(5) 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。
(6) 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。
(7) 图片预加载,将样式表放在顶部,将脚本放在底部 加上时间戳。
(8) 避免在页面的主体布局中使用table,table要等其中的内容完全下载之后才会显示出来,显示比div+css布局慢。