首先,先说一下为何要进行前端优化?
当咱们打开一个网页时,事实上,只有10%-20%的最终用户响应时间是花在从web服务器获取HTML文档并传送到浏览器的,至少80%的最终用户响应时间是花在了页面中的组件上(图片、脚本、样式表、Flash等)、太慢的网站常常会形成访客再也不回返,所以,把精力放在这80%的时间能够极大的改善web的性能。而请求组件须要伴随着HTTP请求,而减小HTTP请求、减少HTTP请求大小等都是改善web性能的最佳实践
下面,让咱们来学学雅虎的14条军规把~
一、规则1:减小HTTP请求
改善响应时间的最简单途径就是减小组件(图片,脚本,样式表、Flash等)的数量,并由此减小http请求的数量
(1)CSS Sprites:将多个图片合并到一个单独的图片中,再结合css的background-position属性一块儿使用,经过合并图片减小http请求(合并后的图片会比分离的图片的总和要小,由于它下降了图片自身的开销(颜色表,格式信息等))
适用场景:若须要在页面中为背景,按钮,导航栏,连接等提供大量图片,可以使用CSS Sprites
(2)合并脚本和样式表:若将css代码和javascript代码分别放在多个文件中,每一个文件都会致使一个额外的http请求,将这些文件合并到一个文件中,能够减小http请求的数量并缩短最终用户时间
注:若不一样页面须要不一样的脚本,可能脚本合并的组合数会比较多
二、规则2:使用内容发布网络
一般来讲,Web客户端离当前Web服务器越近,响应时间会更快
(1)内容发布网络:内容发布网络是一组分布在多个不一样地理位置的Web服务器,用于更加有效地向用户发布内容
(2)一些大型公司都拥有他们本身的CDN,但使用一个CDN服务提供商更为有效
优势:对于地理上分散的用户人群来讲,CDN能轻易地获得响应速度上的提升
除了缩短响应时间以外,CDN还提供备份,扩展存储功能和进行缓存等服务
缺点:CDN服务开销可能比较大,且CDN服务提供商在其全部客户之间共享其Web服务组,可能会受到其它网站流量的影响
没法直接控制组件服务器所带来的特殊麻烦,如修改HTTP响应头必须经过服务器提供商来完成
三、规则3:添加Expires头
(1)主要经过配置组件,使用一个长久的Expires头,使这些组件可以被缓存,使在后续的页面浏览中避免没必要要的http请求(浏览器能够直接从硬盘上读取组件而无需生成任何http流量),web服务器使用Expires头来告诉web客户端它可使用一个组件的当前副本,直到指定的时间为止
(2)长久的Expires头最经常使用于图片,但应该将其应用在全部组件上,包括脚本、样式表和Flash等不常常变化的组件,但添加长久的Expires会带来额外的开发成本
(3)浏览器(和代理)经过使用缓存来减小http请求的数量,并减少http响应的大小,从而使页面加载得更快,Expires在http响应中发送,web服务器经过使用Expires头来告诉Web客户端它可使用一个组件的当前副本
(4)Expires头的限制:Expires头使用一个特定的时间,它要求服务器和客户端的时钟严格同步,另外,若是到了过时时间,须要在服务器配置中提供一个新的日期
(5)Cache-Control头:http1.1引入的,主要用来克服Expires的限制
主要使用max-age指令指定组件被缓存多久
注:能够同时指定Expires和Cache-Control两个响应头,由于有些浏览器不支持http1.1
(6)修订文件名:
为了确保用户可以获取组件的最新版本,须要在全部HTML页面中修改组件的文件名
(7)一个具备长久的Expires头的组件将会被缓存,在后续请求时浏览器直接从磁盘上读取它,避免了一个http请求
若是一个组件没有长久的Expires头,它仍然会存储在浏览器的缓存中,在后续请求中,浏览器会检查缓存并发现组件以及过时。为了提升效率,浏览器会向原始服务器发送一个条件GET请求,若是组件没有改变,原始服务器能够免于发送整个组件,而是发送一个很小的头,告诉浏览器可使用其缓存的组件
四、规则4:压缩组件(使用gzip编码压缩http响应包)
(1)主要经过http响应的大小来减小响应时间,从http1.1开始,Web客户端能够经过http请求中的Accept-Encoding来标识对压缩的支持
若是Web服务器看到请求中有这个头,就会使用客户端列出来的方法中的一种来压缩响应,Web服务器经过响应中的Content-Encoding头来通知Web客户端
(2)压缩什么:通常压缩HTML文档、样式表和脚本
(3)压缩的成本:服务器端会花费额外的CPU周期来完成压缩,客户端要对压缩文件进行解压缩
五、规则5:将样式表放在顶部
(1)将样式表放在底部,可能会延迟页面的加载,会出现“白屏”和“无样式闪烁”,将样式表放在顶部,可使页面逐步呈现,避免页面出现”白屏“和“无样式闪烁”
(2)白屏:浏览器延迟内容呈现,直到全部的样式表都下载完毕后才开始开始显示内容,即页面彻底空白,直到页面全部内容同时涌上屏幕
无样式闪烁:样式表被正确地下载及解析,已经呈现的页面和图片要用新的样式重绘
(3)link和@import:
注:使用@import规则可能会致使白屏现象,即便是放在<head>中
通常组件都是按照它们在页面中出现的顺序下载的,而使用@import会带来下载时的无序性
六、规则6:将脚本放在底部
(1)将脚本放在底部,既可使页面逐步呈现,也能够提升下载的并行度
(2)将样式表放在<head>中,能够首先下载它们而不会阻止页面呈现,使用脚本时,对于全部位于脚本如下的内容,逐步呈现都被阻塞了。将脚本放在页面越靠下的地方,意味着越多的内容可以逐步地呈现
(3)http1.1建议浏览器从每一个主机名并行地下载两个组件。然而,在下载脚本时并行下载实际上是被禁用的,即便是用了不一样的主机名,浏览器也不会启动其余的下载
(4)脚本对web页面的影响:脚本会阻塞其后面内容的呈现,脚本会阻塞其后面组件的下载(脚本会阻塞并行下载)
七、规则7:避免CSS表达式
(1)CSS表达式不仅在页面呈现和大小改变时求值,当页面滚动,甚至连用户鼠标的页面移动时都要求值
八、规则8:使用外部的JavaScript和CSS
(1)在某种程度上,内联会快一些,尽管总下载量时是相同的,但外部示例须要承担多个http请求带来的开销。可是现实中仍是使用外部文件会产生比较快的页面,由于javascript和css文件有可能被浏览器缓存起来
(2)使用外部文件能够提升组件的重用率
九、规则9:减小DNS查找
(1)Internet是经过IP地址来查找服务器的,因为IP地址很难记忆,一般使用包含主机名的URL来代替它,但当浏览器发送其请求时,IP地址仍然是必需的,这就是Domain Name System(DNS)所处的角色。DNS将主机名映射到IP地址上,在输入一个URL时,链接到浏览器的DNS解析器会返回服务器的IP地址
(2)DNS也是开销,在DNS查找完成以前,浏览器不能从主机名那里下载到任何东西,响应时间依赖于DNS解析器(一般由你的ISP提供)
(3)DNS缓存:DNS查找能够被缓存起来以提升性能,在用户请求了一个主机名后,DNS信息会留在操做系统的DNS缓存中,以后对于该主机名的请求将无需进行过多的DNS查找
(4)经过使用keep-Alive和较少的域名来减小DNS查找,keep-Alive经过重用现有链接避免了重复的DNS查找,减小惟一主机名的数量能够减小DNS查找
(5)建议:能够将组件分别放在至少2个,但不要超过4个主机名下,这是在减小DNS查找和容许高度并行下载之间做出的很好的权衡
十、规则10:精简Javascript
(1)精简是从代码中移除没必要要的字符以减少其大小进而改善加载时间,在代码被精简后,全部的注释以及没必要要的空白字符都将被移除
(2)内联的javascript也应该被精简
(3)精简CSS可以带来的节省一般要小于精简javascript,由于css中的注释和空白比javascript中的少,最大的潜在节省来自于优化CSS——合并相同的类,移除不适用的类等
十一、规则11:避免重定向
(1)重定向就是,在网页上设置一个约束条件,条件知足,就自动转入到其它网页、网址
(2)重定向用于将用户从一个url从新路由到另外一个url,重定向有不少种——301和302是最经常使用的两种,重定向会使你的页面变慢,javascript能够经过document.location设置为指望的URL执行重定向
(3)当web服务器向浏览器返回一个重定向时,响应中就会返回一个范围在3xx的状态码,这表示用户代理必需执行进一步操做才能完成请求
注:304并非真的重定向,它用来响应条件GET请求,避免下载已经存在于浏览器缓存中的数据
(4)重定向是如何损伤性能的:重定向会延迟整个HTML文档的传输,在HTML文档到达以前,页面中不会呈现出任何东西,也没有任何组件会被下载
十二、规则12:移除重复脚本
(1)重复脚本损伤性能的方式有两种——没必要要的HTTP请求和执行javascript所浪费的时间
(2)在页面中屡次包含相同的脚本会使页面变慢
在IE中,若是脚本没有被缓存,或在从新加载页面时,会产生额外的http请求
在火狐和IE中,脚本会被屡次求值
1三、规则13:配置ETag
(1)ETag(实体标签)是web服务器和浏览器用于确认缓存组件的一种机制
(2)浏览器下载组件时,会将它们存储到缓存中,在后续的页面查看中,若是缓存的组件是“新鲜”的,浏览器就会从磁盘上读取它,避免产生http请求,若是缓存的组件过时了(或者用户明确地从新加载了页面),浏览器在重用它以前必须首先检查它是否仍然有效,这称为一个条件get请求,若是浏览器缓存中的组件是有效的(即它可以和原始服务器上的组件相匹配),原始服务器不会返回整个组件,而是返回一个304的状态码
(3)服务器在检测缓存的组件是否和原始服务器上的组件匹配时有两种方式:比较最新修改日期,比较实体标签(ETag是惟一标识了一个组件的一个特定版本的字符串)
(4)ETag带来的问题,当浏览器向一台服务器获取了原始组件,又向另外一台不一样的服务器发起条件get请求时,ETag是不会匹配的
(5)即便组件具备长久的Expires头,一旦用户单击了Reload或Refresh按钮。依然会产生条件get请求
1四、规则14:使Ajax可缓存