前端积累-----网页性能优化

写在前面:文章转自网络
英文原版连接 ,如果以为本文哪里很差还请指出,以便及时修改
目录(分7类,共35条):javascript

[内容]尽可能减小HTTP请求数php

[服务器]使用CDN(Content Delivery Network)     css

[服务器]添上Expires或者Cache-Control HTTP头     html

[服务器]Gzip组件     前端

[css]把样式表放在顶部     java

[js]把脚本放在底部     node

[css]避免使用CSS表达式     web

[js, css]把JavaScript和CSS放到外面     算法

[内容]减小DNS查找     数据库

[js, css]压缩JavaScript和CSS    

[内容]避免重定向    

[js]去除重复脚本    

[服务器]配置ETags    

[内容]让Ajax可缓存    

[服务器]尽早清空缓冲区    

[服务器]对Ajax用GET请求    

[内容]延迟加载组件    

[内容]预加载组件    

[内容]减小DOM元素的数量    

[内容]跨域分离组件    

[内容]尽可能少用iframe    

[内容]杜绝404    

[cookie]给Cookie减肥    

[cookie]把组件放在不含cookie的域下    

[js]尽可能减小DOM访问    

[js]用智能的事件处理器    

[css]选择 舍弃@import    

[css]避免使用滤镜    

[图片]优化图片    

[图片]优化CSS Sprite    

[图片]不要用HTML缩放图片    

[图片]用小的可缓存的favicon.ico(P.S. 收藏夹图标)    

[移动端]保证全部组件都小于25K    

[移动端]把组件打包到一个复合文档里    

[服务器]避免图片src属性为空
译文:给网站提速的最佳实践
咱们已经发现了很多给站点提速的最佳实践,分7类共35条。 1.尽可能减小HTTP请求数
分类: 内容
80%的终端用户响应时间都花在了前端上,其中大部分时间都在下载页面上的各类组件:图片,样式表,脚本,Flash等等。减小组件数必然可以减小页面提交的HTTP请求数。这是让页面更快的关键。
减小页面组件数的一种方式是简化页面设计。但有没有一种方法能够在构建复杂的页面同时加快响应时间呢?嗯,确实有鱼和熊掌兼得的办法。
合并文件是经过把全部脚本放在一个文件中的方式来减小请求数的,固然,也能够合并全部的CSS。若是各个页面的脚本和样式不同的话,合并文件就是一项比较麻烦的工做了,但把这个做为站点发布过程的一部分确实能够提升响应时间。
CSS Sprites 是减小图片请求数量的首选方式。把背景图片都整合到一张图片中,而后用CSS的 background-image 和 background-position 属性来定位要显示的部分。
图像映射 能够把多张图片合并成单张图片,总大小是同样的,但减小了请求数并加速了页面加载。图片地图只有在图像在页面中连续的时候才有用,好比导航条。给image map设置坐标的过程既无聊又容易出错,用image map来作导航也不容易,因此不推荐用这种方式。
行内图片(Base64编码)用 data: URL模式 来把图片嵌入页面。这样会增长HTML文件的大小,把行内图片放在(缓存的)样式表中是个好办法,并且成功避免了页面变“重”。但目前主流浏览器并不能很好地支持行内图片。
减小页面的HTTP请求数是个起点,这是提高站点首次访问速度的重要指导原则。就像Tenni Theurer的博客 Browser Cache Usage – Exposed! 里写到的,40%到60%的访客在访问你的站点时,缓存都是空的。因此,加快页面首次访问速度对提升用户体验是极其重要的。 2.使用CDN(Content Delivery Network)
分类: 服务器
用户与服务器的物理距离对响应时间也有影响。把内容部署在多个地理位置分散的服务器上能让用户更快地载入页面。但具体要怎么作呢?
实现内容在地理位置上分散的第一步是:不要尝试去从新设计你的web应用程序来适应分布式结构。这取决于应用程序,改变结构可能包括一些让人望而生畏的任务,好比同步会话状态和跨服务器复制数据库事务(翻译可能不许确)。缩短用户和内容之间距离的提议可能被推迟,或者根本不可能经过,就是由于这个难题。
记住终端用户80%到90%的响应时间都花在下载页面组件上了:图片,样式,脚本,Flash等等,这是 业绩黄金法则 。最好先分散静态内容,而不是一开始就从新设计应用程序结构。这不只可以大大减小响应时间,还更容易表现出CDN的功劳。
内容分发网络(CDN)是一组分散在不一样地理位置的web服务器,用来给用户更高效地发送内容。典型地,选择用来发送内容的服务器是基于网络距离的衡量标准的。例如:选跳数(hop)最少的或者响应时间最快的服务器。
一些互联网公司巨头拥有他们本身的CDN,但用一个CDN服务提供者是比较划算的,好比 Akamai Technologies , EdgeCast ,或者 level3 。对刚刚起步的公司和我的网站来讲,CDN服务的成本是很高的,但若是你的用户群却愈来愈大,愈来愈全球化,那么用CDN来换取更快的响应时间仍是颇有必要的。在Yahoo!,把静态内容从应用程序的web服务器搬到CDN(包括上面提到的3rd party和Yahoo本身的 CDN )可以提升终端用户20%甚至更多的响应时间。换到CDN是一个至关简单的代码变动,但这将急剧提高站点的响应速度。 3.添上Expires或者Cache-Control HTTP头
分类: 服务器
这条规则有两个方面:
    对于静态组件:经过设置一个遥远的未来时间做为 Expires 来实现永不失效     多余动态组件:用合适的 Cache-Control HTTP头来让浏览器进行条件性的请求
网页设计愈来愈丰富,这意味着页面里有更多的脚本,图片和Flash。站点的新访客可能仍是不得不提交几个HTTP请求,但经过使用有效期能让组件变得可缓存,这避免了在接下来的浏览过程当中没必要要的HTTP请求。有效期HTTP头一般被用在图片上,但它们应该用在 全部 组件上,包括脚本、样式和Flash组件。
浏览器(和代理)用缓存来减小HTTP请求的数目和大小,让页面可以更快加载。web服务器经过有效期HTTP响应头来告诉客户端,页面的各个组件应该被缓存多久。用一个遥远的未来时间作有效期,告诉浏览器这个响应在2010年4月15日前不会改变。
Expires: Thu, 15 Apr 2010 20:00:00 GMT
若是你用的是Apache服务器,用ExpiresDefault指令来设置相对于当前日期的有效期。下面的例子设置了从请求时间起10年的有效期:
ExpiresDefault "access plus 10 years"
记住,若是你用一个遥远的将来时间作有效期,就不得不在组件发生变化后及时修改组件的文件名。在Yahoo!,咱们常常把这一步做为构建过程的一部分:把版本号内嵌在组件的文件名里,例如:yahoo_2.0.6.js
用一个遥远的将来时间作有效期HTTP头,只有在用户已经访问过站点以后才会影响页面视图。若是是新访客或者浏览器的缓存被清空时,对HTTP请求的数量并无影响。所以这种性能提高取决于已缓存各个组件的用户访问站点的频率。咱们 在Yahoo!测量了这个数据 ,发现已缓存各个组件的页面访问量(PV)占75%到85%。经过把一个遥远的将来时间做为有效期HTTP头,增长了被浏览器缓存的组件数量,在后续页面访问量中不须要用Internet链接多发送哪怕一个字节。 4.Gzip组件
分类: 服务器
前端工程师能够想办法明显地缩短经过网络传输HTTP请求和响应的时间。毫无疑问,终端用户的带宽速度,网络服务商,对等交换点的距离等等,都是开发团队所没法控制的。但还有别的可以影响响应时间的因素,压缩能够经过减小HTTP响应的大小来缩短响应时间。
从HTTP/1.1开始,web客户端就有了支持压缩的Accept-Encoding HTTP请求头。
Accept-Encoding: gzip, deflate
若是web服务器看到这个请求头,它就会用客户端列出的一种方式来压缩响应。web服务器经过Content-Encoding相应头来通知客户端。
Content-Encoding: gzip
Gzip是目前最多见的高效压缩方法,由GNU项目开发并被 RFC 1952 标准化。惟一一个你可能会看到的其它压缩格式是deflate,但它效率不高并且并不常见。
Gzipping通常可以把响应压缩到70%左右,目前大约90%的经过浏览器的网络传输都支持gzip。若是是Apache服务器,配置gzip的模块取决于版本:Apache 1.3用 mod_gzip 而Apache 2.x是 mod_deflate 模块。
浏览器和代理的某些因素可能会引发浏览器所指望的和它收到的压缩内容不匹配。幸运的是,随着老旧浏览器的淘汰,这些极少遇到的状况正在逐渐减小,并且Apache模块能够经过自动添加合适的Vary响应头来帮你搞定。
服务器会根据文件类型来决定要不要用gzip压缩,但这很是有限。大多数网站都用gzip压缩HTML文件,其实压缩脚本,样式表也是不错的选择,但不少网站却错失了这个机会。其实,能够压缩任何文本内容,包括XML和JSON,而图片和PDF不用压缩,由于它们已经被压缩过了,再用gzip压缩不只浪费CPU还可能会越压越大。
尽量多地用gzip压缩可以给页面减肥,这也是提高用户体验最简单的方法。 5.把样式表放在顶部
分类: css
在Yahoo!研究性能的时候,咱们发现把样式表放到文档的HEAD部分能让页面 看起来 加载地更快。这是由于把样式表放在head里能让页面逐步渲染。
关注性能的前端工程师想让页面逐步渲染。也就是说,咱们想让浏览器尽快显示已有内容,这在页面上有一大堆内容或者用户网速很慢时显得尤其重要。给用户显示反馈(好比进度指标)的重要性已经被普遍研究过,而且被 记录 下来了。在咱们的例子中,HTML页面就是进度指标!当浏览器逐渐加载页面头部,导航条,顶部logo等等内容的时候,这些都被正在等待页面加载的用户看成反馈,可以提升总体用户体验。
在不少浏览器(包括IE)中,把样式表放在HTML文档底部都会阻止页面逐渐渲染。这些浏览器阻塞渲染过程,以免由于样式变更而重绘页面元素,用户这时就只能盯着空白页面。
HTML官方文档 清楚地描述了样式表应该放在页面的HEAD里面:”Unlike A, [LINK] may only appear in the HEAD section of a document, although it may appear any number of times.”(不像a标签,link标签可能只出如今HEAD部分,虽然它能能够出现任意屡次)。空白屏幕或者没有样式的falsh内容都是不可取的。理想方案就是遵循HTML官方文档,把样式表放在HTML文档的HEAD部分。 6.把脚本放在底部
分类: javascript
脚本会阻塞并行下载, HTTP/1.1官方文档 建议浏览器每一个主机名下并行下载的组件数不要超过两个,若是图片来自多个主机名,并行下载的数量就能够超过两个。若是脚本正在下载,浏览器就不开始任何其它下载任务,即便是在不一样主机名下的。
有时候,并不容易把脚本移动到底部。举个例子,若是脚本是用 document.write 插入到页面内容中的,就没办法再往下移了。还可能存在做用域问题,在多数状况下,这些问题都是能够解决的。
一个常见的建议是用推迟(deferred)脚本,有 DEFER 属性的脚本意味着不能含有document.write,而且提示浏览器告诉他们能够继续渲染。不幸的是,Firefox不支持 DEFER 属性。在IE中,脚本可能被推迟,但不尽如人意。若是脚本能够推迟,咱们就能够把它放到页面底部,页面就能够更快地载入。 7.避免使用CSS表达式
分类: css
用CSS表达式动态设置CSS属性,是一种强大又危险的方式。从IE5开始支持,但 从IE8起就不推荐使用了 。例如,能够用CSS表达式把背景颜色设置成按小时交替的:
background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" );
上面的代码中, expression 方法能够接受一个JavaScript表达式。CSS属性会被设置成表达式的计算结果。 expression 方法会被其它浏览器忽略,因此只有想办法实现跨浏览器的与IE一致的用户体验才有用。
表达式最大的问题是它们常常被重复计算,比咱们想象的次数还要多。不只仅是页面渲染和调整大小的时候,在页面被滚动,甚至用户在页面上移动鼠标时都会从新计算表达式。给CSS表达式添加一个计数器就能够追踪它从新计算的时间和频率,而在页面上动动鼠标就能够引起10000屡次从新计算。
减小CSS表达式从新计算的一种方式就是用一次性表达式,即在表达式第一次计算后就把样式属性设置成一个明确的值,换掉表达式。若是必需要在页面的整个生命周期中动态设置样式属性,能够用事件处理器来代替CSS表达式。若是必须使用CSS表达式,要记得它们可能会被重复计算上千次,从而影响整个页面的性能。 8.把JavaScript和CSS放到外面
分类: javascript, css
不少性能原则都是关于如何管理外部组件的,然而,在这些顾虑出现以前你应该问一个更基础的问题:应该把JavaScript和CSS放到外部文件中仍是直接写在页面里?
实际上,用外部文件可让页面更快,由于JavaScript和CSS文件会被缓存在浏览器。HTML文档中的行内JavaScript和CSS在每次请求该HTML文档的时候都会从新下载。这样作减小了所需的HTTP请求数,但增长了HTML文档的大小。另外一方面,若是JavaScript和CSS在外部文件中,而且已经被浏览器缓存起来了,那么咱们就成功地把HTML文档变小了,并且尚未增长HTTP请求数。
关键因素是,外部文件被缓存的频率和页面被请求数量之间的关系。尽管这个因素很难量化,但咱们仍是能够用各类各样的指标来衡量。若是用户的每一个会话中都有屡次页面访问,那么相同的脚本和样式表就能够被多个页面复用,缓存的外部文件就会带来巨大的好处。
不少站点在度量中都处于中等水平,对这些站点来讲,通常最好的解决方案就是把JavaScript和CSS部署为外部文件。惟一的例外是主页上行内方式优先,例如 Yahoo!的首页 和 My Yahoo! 。在每一个会话中访问量比较少的主页会发现行内JavaScript和CSS能让终端用户的响应时间更快。
对典型的站点来讲,首页是众多访问量的开始,有不少技术能够对减小HTTP请求起到杠杆做用,就像用外部文件缓存的好处同样。这样的一种技术就是在首页用行内JavaScript和CSS,但在页面载入完成以后动态加载外部文件,这样后续的页面所需的外部文件就已经被放到浏览器的缓存里了。 9.减小DNS查找
分类: 内容
域名系统创建了主机名和IP地址间的映射,就像电话簿上人名和号码的映射同样。当你在浏览器输入www.yahoo.com的时候,浏览器就会联系DNS解析器返回服务器的IP地址。DNS是有成本的,它须要20到120毫秒去查找给定主机名的IP地址。在DNS查找完成以前,浏览器没法从主机名下载任何东西。
DNS查找被缓存起来更高效,由用户的ISP(网络服务提供商)或者本地网络存在一个特殊的缓存服务器上,但还能够缓存在我的用户的计算机上。DNS信息被保存在操做系统的DNS cache(微软Windows上的”DNS客户端服务”)里。大多数浏览器有独立于操做系统的本身的cache。只要浏览器在本身的cache里还保留着这条记录,它就不会向操做系统查询DNS。
IE默认缓存DNS查找30分钟,写在 DnsCacheTimeout 注册表设置中。Firefox缓存1分钟,能够用 network.dnsCacheExpiration 配置项设置。(Fasterfox把缓存时间改为了1小时 P.S. Fasterfox是FF的一个提速插件)
若是客户端的DNS cache是空的(包括浏览器的和操做系统的),DNS查找数等于页面上不一样的主机名数,包括页面URL,图片,脚本文件,样式表,Flash对象等等组件中的主机名,减小不一样的主机名就能够减小DNS查找。
减小不一样主机名的数量同时也减小了页面可以并行下载的组件数量,避免DNS查找削减了响应时间,而减小并行下载数量却增长了响应时间。个人原则是把组件分散在2到4个主机名下,这是同时减小DNS查找和容许高并发下载的折中方案。 10.压缩JavaScript和CSS
分类: javascript, css
压缩具体来讲就是从代码中去除没必要要的字符以减小大小,从而提高加载速度。代码最小化就是去掉全部注释和没必要要的空白字符(空格,换行和tab)。在JavaScript中这样作可以提升响应性能,由于要下载的文件变小了。两个最经常使用的JavaScript代码压缩工具是 JSMin 和 YUI Compressor ,YUI compressor还能够压缩CSS。
混淆是一种可选的源码优化措施,要比压缩更复杂,因此混淆过程也更容易产生bug。在对美国前十的网站调查中,压缩能够缩小21%,而混淆能缩小25%。虽然混淆的缩小程度更高,但比压缩风险更大。
除了压缩外部脚本和样式,行内的 <script> 和 <style> 块也能够压缩。即便启用了gzip模块,先进行压缩也可以缩小5%或者更多的大小。JavaScript和CSS的用处愈来愈多,因此压缩代码会有不错的效果。 11.避免重定向
分类: 内容
重定向用301和302状态码,下面是一个有301状态码的HTTP头:
HTTP/1.1 301 Moved Permanently       Location: http://example.com/newuri       Content-Type: text/html
浏览器会自动跳转到 Location 域指明的URL。重定向须要的全部信息都在HTTP头部,而响应体通常是空的。其实额外的HTTP头,好比 Expires 和 Cache-Control 也表示重定向。除此以外还有别的跳转方式:refresh元标签和JavaScript,但若是你必须得作重定向,最好用标准的3xxHTTP状态码,主要是为了让返回按钮能正常使用。
牢记重定向会拖慢用户体验,在用户和HTML文档之间插入重定向会延迟页面上的全部东西,页面没法渲染,组件也没法开始下载,直到HTML文档被送达浏览器。
有一种常见的极其浪费资源的重定向,并且web开发人员通常都意识不到这一点,就是URL尾部缺乏一个斜线的时候。例如,跳转到 http://astrology.yahoo.com/astrology 会返回一个重定向到 http://astrology.yahoo.com/astrology/ 的301响应(注意添在尾部的斜线)。在Apache中能够用 Alias , mod_rewrite 或者 DirectorySlash 指令来取消没必要要的重定向。
重定向最多见的用途是把旧站点链接到新的站点,还能够链接同一站点的不一样部分,针对用户的不一样状况(浏览器类型,用户账号类型等等)作一些处理。用重定向来链接两个网站是最简单的,只须要少许的额外代码。虽然在这些时候使用重定向减小了开发人员的开发复杂度,但下降了用户体验。一种替代方案是用 Alias 和 mod_rewrite ,前提是两个代码路径都在相同的服务器上。若是是由于域名变化而使用了重定向,就能够建立一条CNAME(建立一个指向另外一个域名的DNS记录做为别名)结合 Alias 或者 mod_rewrite 指令。 12.去除重复脚本
分类: javascript
页面含有重复的脚本文件会影响性能,这可能和你想象的不同。在对美国前10大web站点的评审中,发现只有2个站点含有重复脚本。两个主要缘由增长了在单一页面中出现重复脚本的概率:团队大小和脚本数量。在这种状况下,重复脚本会建立没必要要的HTTP请求,执行无用的JavaScript代码,而影响页面性能。
IE会产生没必要要的HTTP请求,而Firefox不会。在IE中,若是一个不可缓存的外部脚本被页面引入了两次,它会在页面加载时产生两个HTTP请求。即便脚本是可缓存的,在用户从新加载页面时也会产生额外的HTTP请求。
除了产生没有意义的HTTP请求以外,屡次对脚本求值也会浪费时间。由于不管脚本是否可缓存,在Firefox和IE中都会执行冗余的JavaScript代码。
避免不当心把相同脚本引入两次的一种方法就是在模版系统中实现脚本管理模块。典型的脚本引入方法就是在HTML页面中用SCRIPT标签:
<script type="text/javascript" src="menu_1.0.17.js"></script>
PHP中一个可选方案是建立一个叫 insertScript 的函数:
<?php insertScript("menu.js") ?>
除了防止相同脚本被屡次引入,这个函数还能够解决脚本相关的其它问题,好比依赖性检查和给脚本文件名添加版本号来支持“永久”有效期HTTP头。 13.配置ETags
分类: 服务器
实体标签(ETags),是服务器和浏览器用来决定浏览器缓存中组件与源服务器中的组件是否匹配的一种机制(“实体”也就是组件:图片,脚本,样式表等等)。添加ETags能够提供一种实体验证机制,比最后修改日期更加灵活。一个ETag是一个字符串,做为一个组件某一具体版本的惟一标识符。惟一的格式约束是字符串必须用引号括起来,源服务器用相应头中的 ETag 来指定组件的ETag:
HTTP/1.1 200 OK       Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT       ETag: "10c24bc-4ab-457e1c1f"       Content-Length: 12195
而后,若是浏览器必须验证一个组件,它用 If-None-Match 请求头来把ETag传回源服务器。若是ETags匹配成功,会返回一个304状态码,这样就减小了12195个字节的响应体。
GET /i/yahoo.gif HTTP/1.1       Host: us.yimg.com       If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT       If-None-Match: "10c24bc-4ab-457e1c1f"       HTTP/1.1 304 Not Modified
ETags存在的问题是它们是由特定服务器构造的,因此若是浏览器从一个服务器获取最初的组件,而后想验证另外一个服务器上的相同组件,ETags是没法匹配成功的,而用一群服务器处理请求在web站点中又很是广泛。默认状况下,Apache和IIS会在ETag中嵌入数据,以大大下降在多服务器站点上有效性测试成功的概率。
Apache 1.3和2.x中ETag的格式是 inode-size-timestamp 。就算给定的文件可能在多个服务器的相同目录下,并且文件大小、访问权限、时间戳等等所有相同,它的i节点(P.S. inode,UNIX中的索引文件)在不一样服务器中也不同。
IIS5.0和6.0也都存在相似的问题。IIS中ETags的格式是 Filetimestamp:ChangeNumber , ChangeNumber 是一个用来追踪IIS配置变动的计数器。 一个站点在不一样的IIS服务器上的 ChangeNumber 是不可能相同的。
最终结果是Apache和IIS为彻底相同的组件生成的ETags没法跨浏览器匹配,若是ETags不匹配,用户就没法收到为又小又快的304响应设计的ETags。反而,他们将收到一个携带着组件全部数据的200正常响应。若是站点部署在单一服务器上,就根本不存在这个问题。但若是站点部署在多个服务器上,并且打算用Apache或者IIS的默认ETags配置,用户将看到缓慢的页面,服务器负载更高,还会消耗更大的带宽,而且代理也没法有效缓存页面内容。即便组件有“永久” Expires HTTP头,用户点击从新加载或者刷新的时候,仍然会发出条件GET请求。
若是不想用ETags提供的灵活的验证模型,最好把全部的Etag全都去掉,能够用基于组件的时间戳的 Last-Modified HTTP头验证,并且去掉ETag能够减小HTTP响应头以及后续请求的大小。 Microsoft Support article 里写了怎样移除ETags。在Apache中,能够简单地经过在Apache配置文件中添上以下代码来实现:
FileETag none
14.让Ajax可缓存
分类: 内容
Ajax的一个好处是能够给用户提供即时反馈,由于它可以从后台服务器异步请求信息。然而,用了Ajax就没法保证用户在等待异步JavaScript和XML响应返回期间不会很是无聊。在不少应用程序中,用户可以一直等待取决于如何使用Ajax。例如,在基于web的电子邮件客户端中,用户为了寻找符合他们搜索标准的邮件消息,将会保持对Ajax请求返回结果的关注。重要的是,要记得“异步”并不意味着“即时”。
要提升性能,优化这些Ajax响应相当重要。最重要的提升Ajax性能的方法就是让响应变得可缓存,就像在 添上Expires或者Cache-Control HTTP头 中讨论的同样。下面适用于Ajax的其它规则:
    Gzip组件     减小DNS查找     压缩JavaScript     避免重定向     配置ETags
咱们一块儿看看例子,一个Web 2.0的电子邮件客户端用了Ajax来下载用户的通信录,以便实现自动完成功能。若是用户从上一次使用以后再没有修改过她的通信录,并且Ajax响应是可缓存的,有还没有过时的Expires或者Cache-Control HTTP头,那么以前的通信录就能够从缓存中读出。必须通知浏览器,应该继续使用以前缓存的通信录响应,仍是去请求一个新的。能够经过给通信录的Ajax URL里添加一个代表用户通信录最后修改时间的时间戳来实现,例如 &t=1190241612 。若是通信录从上一次下载以后再没有被修改过,时间戳不变,通信录就将从浏览器缓存中直接读出,从而避免一次额外的HTTP往返消耗。若是用户已经修改了通信录,时间戳也能够确保新的URL不会匹配缓存的响应,浏览器将请求新的通信录条目。
即便Ajax响应是动态建立的,并且可能只适用于单用户,它们也能够被缓存,而这样会让你的Web 2.0应用更快。 15.尽早清空缓冲区
分类: 服务器
当用户请求一个页面时,服务器须要用大约200到500毫秒来组装HTML页面,在这期间,浏览器闲等着数据到达。PHP中有一个 flush() 函数,容许给浏览器发送一部分已经准备完毕的HTML响应,以便浏览器能够在后台准备剩余部分的同时开始获取组件,好处主要体如今很忙的后台或者很“轻”的前端页面上(P.S. 也就是说,响应时耗主要在后台方面时最能体现优点)。
比较理想的清空缓冲区的位置是HEAD后面,由于HTML的HEAD部分一般更容易生成,而且容许引入任何CSS和JavaScript文件,这样就可让浏览器在后台还在处理的时候就开始并行获取组件。
例如:
... <!-- css, js -->     </head>     <?php flush(); ?>     <body>       ... <!-- content -->
Yahoo!搜索 开创了这项技术,并且真实用户测试研究也证实了使用这种技术的诸多好处。 16.对Ajax用GET请求
分类: 服务器
Yahoo!邮箱 团队发现使用 XMLHttpRequest 时,浏览器的POST请求是经过一个两步的过程来实现的:先发送HTTP头,在发送数据。因此最好用GET请求,它只须要发送一个TCP报文(除非cookie特别多)。IE的URL长度最大值是2K,因此若是要发送的数据超过2K就没法使用GET了。
POST请求的一个有趣的反作用是实际上没有发送任何数据,就像GET请求同样。正如 HTTP说明文档 中描述的,GET请求是用来检索信息的。因此它的语义只是用GET请求来请求数据,而不是用来发送须要存储到服务器的数据。 17.延迟加载组件
分类: 内容
能够凑近看看页面并问本身:什么才是一开始渲染页面所必须的?其他内容均可以等会儿。
JavaScript是分隔onload事件以前和以后的一个理想选择。例如,若是有JavaScript代码和支持拖放以及动画的库,这些均可以先等会儿,由于拖放元素是在页面最初渲染以后的。其它能够延迟加载的部分包括隐藏内容(在某个交互动做以后才出现的内容)和折叠的图片。
工具可帮你减轻工做量: YUI Image Loader 能够延迟加载折叠的图片,还有 YUI Get utility 是一种引入JS和CSS的简单方法。 Yahoo!主页 就是一个例子,能够打开Firebug的网络面板仔细看看。
最好让性能目标符合其它web开发最佳实践,好比“渐进加强”。若是客户端支持JavaScript,能够提升用户体验,但必须确保页面在不支持JavaScript时也能正常工做。因此,在肯定页面运行正常以后,能够用一些延迟加载脚本加强它,以支持一些拖放和动画之类的华丽效果。 18.预加载组件
分类: 内容
预加载可能看起来和延迟加载是相反的,但它其实有不一样的目标。经过预加载组件能够充分利用浏览器空闲的时间来请求未来会用到的组件(图片,样式和脚本)。用户访问下一页的时候,大部分组件都已经在缓存里了,因此在用户看来页面会加载得更快。
实际应用中有如下几种预加载的类型:
    无条件 预加载——尽快开始加载,获取一些额外的组件。google.com就是一个sprite图片预加载的好例子,这个sprite图片并非google.com主页须要的,而是搜索结果页面上的内容。     条件性 预加载——根据用户操做猜想用户将要跳转到哪里并据此预加载。在 search.yahoo.com 的输入框里键入内容后,能够看到那些额外组件是怎样请求加载的。     提早 预加载——在推出新设计以前预加载。常常在从新设计以后会听到:“这个新网站不错,但比之前更慢了”,一部分缘由是用户访问先前的页面都是有旧缓存的,但新的倒是一种空缓存状态下的体验。能够经过在将要推出新设计以前预加载一些组件来减轻这种负面影响,老站能够利用浏览器空闲的时间来请求那些新站须要的图片和脚本。
19.减小DOM元素的数量
分类: 内容
一个复杂的页面意味着要下载更多的字节,并且用JavaScript访问DOM也会更慢。举个例子,想要添加一个事件处理器的时候,循环遍历页面上的500个DOM元素和5000个DOM元素是有区别的。
大量的DOM元素是一种征兆——页面上有些内容无关的标记须要清理。正在用嵌套表格来布局吗?仍是为了修复布局问题而添了一堆的 <div> s?或许应该用更好的语义化标记。
YUI CSS utilities 对布局有很大帮助:grids.css针对总体布局,fonts.css和reset.css能够用来去除浏览器的默认格式。这是个开始清理和思考标记的好机会,例如只在语义上有意义的时候使用 <div> ,而不是由于它可以渲染一个新行。
DOM元素的数量很容易测试,只须要在Firebug的控制台里输入: document.getElementsByTagName('*').length
那么多少DOM元素才算是太多呢?能够参考其它相似的标记良好的页面,例如 Yahoo!主页 是一个至关繁忙的页面,但只有不到700个元素(HTML标签)。 20.跨域分离组件
分类: 内容
分离组件能够最大化并行下载,但要确保只用不超过2-4个域,由于存在DNS查找的代价。例如,能够把HTML和动态内容部署在 www.example.org ,而把静态组件分离到 static1.example.org 和 static2.example.org 。
更多信息请查看Tenni Theurer和Patty Chi的文章: Maximizing Parallel Downloads in the Carpool Lane 21.尽可能少用iframe
分类: 内容
用iframe能够把一个HTML文档插入到父文档里,重要的是明白iframe是如何工做的并高效地使用它。
<iframe> 的优势:
    引入缓慢的第三方内容,好比标志和广告     安全沙箱     并行下载脚本
<iframe> 的缺点:
    代价高昂,即便是空白的iframe     阻塞页面加载     非语义
22.杜绝404
分类: 内容
HTTP请求代价高昂,彻底没有必要用一个HTTP请求去获取一个无用的响应(好比404 Not Found),只会拖慢用户体验而没有任何好处。
有些站点用的是有帮助的404——“你的意思是xxx?”,这样作有利于用户体验,,但也浪费了服务器资源(好比数据库等等)。最糟糕的是连接到的外部JavaScript有错误并且结果是404。首先,这种下载将阻塞并行下载。其次,浏览器会试图解析404响应体,由于它是JavaScript代码,须要找出其中可用的部分。 23.给Cookie减肥
分类: cookie
使用cookie的缘由有不少,好比受权和个性化。HTTP头中cookie信息在web服务器和浏览器之间交换。重要的是保证cookie尽量的小,以最小化对用户响应时间的影响。
更多信息请查看Tenni Theurer和Patty Chi的文章: When the Cookie Crumbles 。相关经验原则能够总结以下:
    清除没必要要的cookie     保证cookie尽量小,以最小化对用户响应时间的影响     注意给cookie设置合适的域级别,以避免影响其它子域     设置合适的有效期,更早的有效期或者none能够更快的删除cookie,提升用户响应时间
24.把组件放在不含cookie的域下
分类: cookie
当浏览器发送对静态图像的请求时,cookie也会一块儿发送,而服务器根本不须要这些cookie。因此它们只会形成没有意义的网络通讯量,应该确保对静态组件的请求不含cookie。能够建立一个子域,把全部的静态组件都部署在那儿。
若是域名是 www.example.org ,能够把静态组件部署到 static.example.org 。然而,若是已经在顶级域 example.org 或者 www.example.org 设置了cookie,那么全部对 static.example.org 的请求都会含有这些cookie。这时候能够再买一个新域名,把全部的静态组件部署上去,并保持这个新域名不含cookie。Yahoo!用的是 yimg.com ,YouTube是 ytimg.com ,Amazon是 images-amazon.com 等等。
把静态组件部署在不含cookie的域下还有一个好处是有些代理可能会拒绝缓存带cookie的组件。有一点须要注意:若是不知道应该用example.org仍是www.example.org做为主页,能够考虑一下cookie的影响。省略www的话,就只能把cookie写到 *.example.org ,因此由于性能缘由最好用www子域,而且把cookie写到这个子域下。 25.尽可能减小DOM访问
分类: javascript
用JavaScript访问DOM元素是很慢的,因此,为了让页面反应更迅速,应该:
    缓存已访问过的元素的索引     先“离线”更新节点,再把它们添到DOM树上     避免用JavaScript修复布局问题
更多信息请查看YUI影院里Julien Lecomte的文章: High Performance Ajax Applications 26.用智能的事件处理器
分类: javascript
有时候感受页面反映不够灵敏,是由于有太多频繁执行的事件处理器被添加到了DOM树的不一样元素上,这就是推荐使用 事件委托 的缘由。若是一个 div 里面有10个按钮,应该只给div容器添加一个事件处理器,而不是给每一个按钮都添加一个。事件可以冒泡,因此能够捕获事件并得知哪一个按钮是事件源。
不须要为了处理DOM树而等待onload事件,一般只要目标元素在DOM树中可访问便可,而没必要等待全部的图片下载完成。能够考虑用 DOMContentLoaded 来代替onload事件,但为了让它在全部浏览器中均可用,能够用 YUI Event 工具,它有一个 onAvailable 方法。
更多信息请查看YUI影院里Julien Lecomte的文章: High Performance Ajax Applications 27.选择<link>舍弃@import
分类: css
前面提到了一个最佳实践:为了实现逐步渲染,CSS应该放在顶部。
在IE中用 @import 与在底部用 <link> 效果同样,因此最好不要用它。 28.避免使用滤镜
分类: css
IE专有的 AlphaImageLoader 滤镜能够用来修复IE7以前的版本中半透明PNG图片的问题。在图片加载过程当中,这个滤镜会阻塞渲染,卡住浏览器,还会增长内存消耗并且是被应用到每一个元素的,而不是每一个图片,因此会存在一大堆问题。
最好的方法是干脆不要用 AlphaImageLoader ,而优雅地降级到用在IE中支持性很好的PNG8图片来代替。若是非要用 AlphaImageLoader ,应该用下划线hack: _filter 来避免影响IE7及更高版本的用户。 29.优化图片
分类: 图片
设计师作好图片后,在把这些图片经过FTP上传到web服务器以前,咱们还能够作一些事情。
    检查GIF图片,看看图片中是否是用了调色板大小对应的颜色数,用 imagemagick 能够简单地检查:     identify -verbose image.gif     若是4色图片用了调色板中256色的“槽”,那就还有改进的余地     试着把GIF图片转换成PNG,看能不能缩减大小,每每能够。开发者一般不肯意用PNG图片,由于浏览器支持有限,但这都是过去的事情了。真正的问题是PNG图片彻底支持alpha透明度,而GIF图片却不支持透明度渐变,因此GIF能作的任何事情,PNG均可以(除了动画)。下面这个简单的命令就能让PNG图片能够安全使用:     convert image.gif image.png     “咱们强调的是:给PNG一个机会。”     用 pngcrush (或者其它的PNG优化工具)处理全部的PNG图片,例如:     pngcrush image.png -rem alla -reduce -brute result.png     用jpegtran处理全部JPEG图片,这个工具支持对JPEG图片的无损操做好比旋转,还能够用来去除注释和其它无用信息(好比EXIF信息 P.S. 数码照片信息,焦距光圈之类的):     jpegtran -copy none -optimize -perfect src.jpg dest.jpg
30.优化CSS Sprite
分类: 图片
    在Sprite图片中横向排列通常都比纵向排列的最终文件小     组合Sprite图片中的类似颜色能够保持低色数,最理想的是256色如下PNG8格式     “对移动端友好”,不要在Sprite图片中留下太大的空隙。虽然不会在很大程度上影响图片文件的大小,但这样作能够节省用户代理把图片解压成像素映射时消耗的内存。100×100的图片是1万个像素,而1000×1000的图片就是100万个像素了。
31.不要用HTML缩放图片
分类: 图片
不要由于在HTML中能够设置宽高而使用本不须要的大图。若是须要 <img width="100" height="100" src="mycat.jpg" alt="My Cat" />
那么图片自己(mycat.jpg)应该是100x100px的,而不是去缩小500x500px的图片。 32.用小的可缓存的favicon.ico(P.S. 收藏夹图标)
分类: 图片
favicon.ico是放在服务器根目录的图片,它会带来一堆麻烦,由于即使你无论它,浏览器也会自动请求它,因此最好不要给一个 404 Not Found 响应。并且只要在同一个服务器上,每次请求它时都会发送cookie,此外这个图片还会干扰下载顺序,例如在IE中,当你在onload中请求额外组件时,将会先下载favicon。
因此为了缓解favicon.ico的缺点,应该确保:
    足够小,最好在1K如下     设置合适的有效期HTTP头(之后若是想换的话就不能重命名了),把有效期设置为几个月后通常比较安全,能够经过检查当前favicon.ico的最后修改日期来确保变动能让浏览器知道。
Imagemagick 能够用来处理小收藏夹图标 33.保证全部组件都小于25K
分类: 移动
这个限制是由于iPhone不能缓存大于25K的组件,注意这里指的是 未压缩的 大小。这就是为何缩减内容自己也很重要,由于单纯的gzip可能不够。
更多信息请查看Wayne Shea和Tenni Theurer的文章: Performance Research, Part 5: iPhone Cacheability – Making it Stick 34.把组件打包到一个复合文档里
分类: 移动
把各个组件打包成一个像有附件的电子邮件同样的复合文档里,能够用一个HTTP请求获取多个组件(记住一点:HTTP请求是代价高昂的)。用这种方式的时候,要先检查用户代理是否支持(iPhone就不支持)。 35.避免图片src属性为空
分类: 服务器
Image with empty string src 属性是空字符串的图片很常见,主要以两种形式出现:
    straight HTML
    <img src=””>     JavaScript
    var img = new Image();img.src = “”;
这两种形式都会引发相同的问题:浏览器会向服务器发送另外一个请求。
    IE 向页面所在目录发起一个请求     Safari和Chrome 想当前页面自己发送一个请求     Firefox 3及更早版本与Safari和Chrome处理方式同样,但3.5解决了这个问题 [bug 444931] ,不会再发送请求了     Opera 遇到有空src属性的图片不作任何处理
为何图片src属性为空很差?
    意外发送大量的通讯量对服务器来讲是很伤的,尤为是在天天有几百万访问量页面的时候。     浪费服务器资源去生成一个根本不可能被看到的页面     可能会污染用户数据,若是追踪请求状态,要么经过cookie要么是其它方式,可能会破坏用户数据。即便图片请求并无返回图片,整个HTTP头部也会被浏览器接受并读取,包括全部的cookie。虽然其他部分会被丢弃,但这可能已经形成破坏了。
问题的根本缘由是各个浏览器在处理URI时的分歧,这在RFC 3986 – Uniform Resource Identifiers文档中有明肯定义。若是URI是一个空串,会被看做一个相对URI,并按照5.2节定义的算法处理。实际状况是,Firefox、Safari和Chrome都是根据文档中5.4节列出的规范来处理空串,而IE并无正确处理。听说在旧版本规范文档RFC 2396 – Uniform Resource Identifiers(被RFC 3986废弃了)中,因此从严格意义上来讲浏览器处理相对URI的作法都是对的。问题是,在这种情形下,空串显然是无意的(P.S. 而不是什么相对URI)。
HTML5的4.8.2节有关于<img>标签src属性的描述,规定浏览器再也不发送额外请求:
The src attribute must be present, and must contain a valid URL referencing a non-interactive, optionally animated, image resource that is neither paged nor scripted. If the base URI of the element is the same as the document’s address, then the src attribute’s value must not be the empty string.(P.S. “src属性必须存在,并且必须有一个合法的URL引用非交互式的动画或者图像资源,不能分页也不能含有脚本。若是元素的基URI和文档地址相同,那么src属性的值就不能是空串。”)
但愿未来浏览器不会存在这个问题,不幸的是,没有针对<script src=””>和<link href=””>条款,也许还有时间调整,以确保浏览器不会意外地实现这一行为。
这条原则是受了Yahoo!的JavaScript大师Nicolas C. Zakas的启发,更多信息请查看他的文章: Empty image src can destroy your site

分享到:
相关文章
相关标签/搜索