雅虎14条 - 前端优化
Make Fewer HTTP Requests
尽可能的减少 HTTP 的请求数。
http请求是要开销的,想办法减少请求数自然可以提高网页速度。常用的方法,合并css,js以及image和css sprites等。
css sprites是指将页面上的背景图合并成一张,然后通过css的background-position属性定义不过的值来取他的背景。可以使用http://www.csssprites.com/ 这个工具。
yahoo甚至建议将首页的css和js 直接写在页面文件里面,而不是外部引用。因为首页的访问量太大了,这么做也可以减少两个请求数。
Use a Content Delivery Network
使用CDN(内容分发网络)。
CDN其实是一种新的网络架构,将网站的内容发布到最接近用户的cache服务器上。再通过DNS的负载均衡的技术,判断用户来源最接近于哪个cache服务器,从而将内容直接给到用户,这样传输的距离就减少了,从而有效地减少了数据传输的时间,提高了速度。
CDN出现之前存在的问题
- 网站服务器的性能和带宽就是瓶颈所在;访问量过大时,则瓶颈问题更为明显
- 增大了中间节点的数量,造成了更多的延时。当距离较远时,延时更为明显
- 不同网络运营商之间的胡同的带宽有限,当跨运营商通信时,则延时更为明显
- 中心化过于严重
CDN的原理与核心技术
CDN就是将网站的内容分发到遍布各个地区的边缘节点上,即增加一层Cache缓存层,同时通过负载均衡系统用户的请求合理调度到最合适的边缘节点上,以及节点内的服务器中。
CDN层位于用户端和站点服务器之间,它包含如下东西:
- 智能调度DNS:智能调度DNS是CDN服务中的关键系统,当用户访问加入CDN服务的网站时,域名解析请求将最终由 “智能调度DNS”负责处理。它通过一定的算法和策略,将最合适的CDN节点的IP返回给用户;同时,它还需要与分散在各地的CDN节点保持通信,跟踪节点的状态,确保将用户的请求分配到就近可用的节点上。
- Cache服务器:Cache服务器具有缓存功能,所以大部分网页对象,在有效期(TTL)内,对于重复的访问,不必从原始网站重新传送文件实体, 只需通过简单的认证,即可将本地的副本直接传送给访问者。
CDN解决了:
- 解决了不同运营商之间通信的带宽瓶颈问题
- 缓解了站点服务器的压力
- 缓解了骨干网络的压力
具体的工程流程
传统的方式流程:
- 用户输入访问的域名,操作系统向 LocalDns 查询域名的ip地址.
- LocalDns向 ROOT DNS 查询域名的授权服务器(这里假设LocalDns缓存过期)
- ROOT DNS将域名授权dns记录回应给 LocalDns
- LocalDns得到域名的授权dns记录后,继续向域名授权dns查询域名的ip地址
- 域名授权dns 查询域名记录后,回应给 LocalDns
- LocalDns 将得到的域名ip地址,回应给 用户端
- 用户得到域名ip地址后,访问站点服务器
- 站点服务器应答请求,将内容返回给客户端.
CDN的方式流程:
- 用户输入访问的域名,操作系统向 LocalDns 查询域名的ip地址.
- LocalDns向 ROOT DNS 查询域名的授权服务器(这里假设LocalDns缓存过期)
- ROOT DNS将域名授权dns记录回应给 LocalDns
- LocalDns得到域名的授权dns记录后,继续向域名授权dns查询域名的ip地址
- 域名授权dns 查询域名记录后(一般是CNAME),回应给 LocalDns
- LocalDns 得到域名记录后,向智能调度DNS查询域名的ip地址
- 智能调度DNS 根据一定的算法和策略(比如静态拓扑,容量等),将最适合的CDN节点ip地址回应给 LocalDns
- LocalDns 将得到的域名ip地址,回应给 用户端
- 用户得到域名ip地址后,访问站点服务器
- CDN节点服务器应答请求,将内容返回给客户端.(缓存服务器一方面在本地进行保存,以备以后使用,二方面把获取的数据返回给客户端,完成数据服务过程)
网站接入CDN
- 将需要加速的域名,添加一个由CDN提供的CNAME。这样用户在访问加速域名时,实际上会访问到这个CNAME。
- CNAME在解析时会使用CDN的权威域名服务器。在那里根据DNS,去判断用户的物理位置和运营商情况等,然后返回边缘节点服务器ip客户端。
- 客户端再次请求返回的ip,边缘节点服务器由本地负载均衡服务器根据用户请求内容、节点服务器状态等动态因素去判断哪台服务器可以提供服务,通过302重定向到那台服务器。
CDN加速类型
- 静态内容加速:比如视频、图片、网页等
- 动态内容加速:社交网站的时间线、购物网站的搜索结果等动态网页
Add an Expires Header
即添加缓存控制,以及缓存过期控制。
现在越来越多的图片,脚本,css,flash被嵌入到页面中,当我们访问他们的时候势必会做许多次的http请求。其实我们可以通过设置Expires header 来缓存这些文件。Expire其实就是通过header报文来指定特定类型的文件在览器中的缓存时间。大多数的图片,flash在发布后都是不需要经常修改的,做了缓存以后这样浏览器以后就不需要再从服务器下载这些文件而是而直接从缓存中读取,这样再次访问页面的速度会大大加快。
Gzip Components
启用Gzip压缩。
Gzip的思想就是把文件先在服务器端进行压缩,然后再传输。这样可以显著减少文件传输的大小。传输完毕后浏览器会 重新对压缩过的内容进行解压缩,并执行。
而且gzip的压缩比例非常大,一般压缩率为85%。
Put Stylesheets at the Top
将css放在页面最上面。
这是因为浏览器在css全部传输完成之前是不会渲染任何东西的,z合适因为CSS是可以被覆盖的,即后面的css可以覆盖前面的css,级别高的css可以覆盖级别低的css。所以,等全部加载完再去渲染是最合理的。
Put Scripts at the Bottom
将script放在页面最下面。
这有2个方面的考虑:
- js脚本的执行会阻塞页面。在页面loading的过程中,当浏览器读到js执行语句的时候一定会把它全部解释完毕后在会接下来读下 面的内容。
- 浏览器这么做的逻辑是因为js随时可能执行location.href或是其他可能完全中断此页面过程的函数,既然如此,所以就等他执行完成。所以放在页面最后,可以有效减少页面可视元素的加载时间。
- js会阻塞并行下载数量。当脚本文件下载时,浏览器不会启动其他的并行下载。
Avoid CSS Expressions
避免使用CSS表达式。
表达式的问题就在于它的计算频率要比我们想象的多。不仅仅是在页面显示和缩放时,就是在页面滚动、乃至移动鼠标时都会要重新计算一次。给CSS表达式增加一个计数器可以跟踪表达式的计算频率。在页面中随便移动鼠标都可以轻松达到10000次以上的计算量。
什么是CSS表达式?
<body>
计算了<input id="c" />次
<script type="text/javascript">
var k = 0;
function test() {
k++;
document.getElementById('c').value = k;
return;
}
</script>
<div>
<ul>
<li><a href="11111111111111111111">22222</a></li>
<li><a href="11111111111111111111">22222</a></li>
<li><a href="11111111111111111111">22222</a></li>
<li><a href="11111111111111111111">22222</a></li>
</ul>
</div>
</body>
body {
font-size:12px;
font-family:Verdana;
line-height:1.9
}
div a {
display:block;
border:1px solid #FF3366;
width:expression(this.offsetWidth > 750 ? test() : test());
}
Make JavaScript and CSS External
把javascript和css都放到外部文件中。
这个主要是便于代码的维护。
Reduce DNS Lookups
减少DNS查询。
一次DNS的解析过程会消耗20-120毫秒的 时间,在dns查询结束之前,浏览器不会下载该域名下的任何东西。
yahoo的建议一个页面所包含的域 名数尽量控制在2-4个。
Minify JavaScript
压缩 JavaScript 和 CSS。
减少了页面字节数,下载速度加快,加密了源代码。常用的压缩工具有JsMin、YUI compressor等。另外像http://dean.edwards.name/packer/还给我们提供了一个非常方便的在线压缩工具。
Avoid Redirects
避免重定向。每增加一次重定向就会增加一次web请求,所以因该尽量减少。
Remove Duplicate Scripts
移除重复的脚本。
Configure ETags
配置实体标签(ETags),跟上面的cache-control是一样的,减少请求。