花两天时间看完了《高性能网站建设指南》,为了确保有所消化,特地摘录了笔记,供各位参考。
主要是14条网站性能优化的法则:
规则一:减少HTTP请求
1、 图片地图:允许在一个图片上关联多个URL,目标URL的选择取决于用户点击了图片上的哪个位置。
2、 CSS Sprites(css精灵):需要将多个图片合并在一个单独的图片上,根据css的background属性定位到对应的图标上。图片地图中的图片必须是连续的,而css Sprites则没有这个限制。
3、 内联图片:通过使用data:URL模式可以在WEB页面中包含图片但无需任何额外的HTTP请求。Data:URL模式的主要缺陷在于不受IE的支持(包括7),另一个缺陷就是可能存在数据大小上的限制。
PHP函数file_get_contents可以很容易地通过从磁盘中读取图片并将其内容插入到页面中来创建内联图片。
将内联图片放置在外部,可以从缓存中得到额外收获。
4、 合并脚本和样式表:多个脚本合并为一个脚本,多个样式表合并为一个样式表。
规则二:使用内容发布网络
如果应用程序Web服务器离用户更近,则一个HTTP请求的响应时间将缩短。
内部发布网络(cdn)是一组分布在多个不同地理位置的Web服务器,用于更加有效地向用户发布内容。除了缩短响应时间之外,CDN还可以带来其他优势。他们的服务包括备份,扩展存储能力和进行缓存。
依赖CDN的一个缺点就是你的响应时间可能会受到其他网站的流量的影响,第二就是无法直接控制组件服务器所带来的特殊麻烦。例如:修改http响应头必须通过服务提供商而不是自己,而且如果CDN的服务性能下降,你的工作质量也随之下降。
CDN用于发布静态内容,如图片,脚本,样式表和Flash。
规则三:添加Expires头
Web服务器使用Expires头来告诉Web客户端它可以使用一个组件的当前副本,知道指定的时间为止。HTTP规范中简要地称该头为“在这一日期/时间之后,响应将被认为是无效的”。
为了克服Expires的限制(因为Expires使用一个特定的事件,这要求服务器和客户端的时钟要严格同步,而且过期日期需要经常检查,若到期则需要服务器提供一个新日期。)HTTP1.1引入了Cache-Control头,使用max-age指定指定组件被缓存多久。它以秒为单位定义。
虽然Cache-Control解决了Expires的限制,但对于不支持HTTP1.1的浏览器,你可能仍然希望提供Expires头。
Expires和Cache-Control的max-age同时存在时,Cache-Control具有优先权并且明确指出了相对于请求时间所经过的秒数。
Expires不仅仅应用于图片,而应该包含任何不经常变化的组件,如脚本,样式白哦和flash组件。
如果想在Expires过期前更新所缓存的组件,则只需要修改文件名即可,一般讲版本号嵌入组件的文件名内,修改版本号即可自动更新。
如果一个组件没有长久的Expires头,它仍然会存储在浏览器的缓存中。但在后续的请求中,浏览器会检查缓存并发现组件已经过期,就会向服务器发送一个条件GET请求来检查,若未改变则接收到304状态码。而通过使用Expires头则可以避免额外的HTTP请求,对应减少响应时间。
规则四:压缩组件
从HTTP1.1开始,Web客户端可以通过HTTP请求中的Accept-Encoding头来表示对压缩的支持。(Accept-Encoding:gzip,deflate)而如果Web服务器看到请求有这个头,就会使用客户端列出来的方法中的一种来压缩响应,Web服务器通过响应中的Content-Encoding头来通知Web客户端采用了何种压缩。(Content-Encoding:gzip)
压缩的成本有:服务器端会花费额外的CPU周期来完成压缩,客户端要对压缩文件进行解压缩。
代理缓存:为了避免不同的浏览器请求相同的代理时出现差异(一个浏览器支持gzip,另一个浏览器不支持gzip),而导致获取不到正确的数据。可以在服务器的Vary响应头中包含Accept-Encoding来解决。(Vary:Accept-Encoding),这样代理就会缓存每个响应的两个版本——Accept-Encoding为gzip的压缩内容和没有指定Accept-Encoding时的非压缩内容。
边缘情形:无论是服务器还是客户端发送了错误,页面都会被破坏。可以通过Cache-Control:private来为所有浏览器禁用代理缓存。
规则五:将样式表放在顶部
当样式表放在文档底部会导致在浏览器中阻止内容逐步呈现,浏览器会延迟显示任何可视化组件,这种现象称为白屏。
使用LINK标签将样式表放在文档HEAD中,可以解决白屏和无样式内容的闪烁。
规则六:将脚本放在底部
使用脚本时,对于所有位于脚本以下的内容,逐步呈现都被阻塞了,也阻塞了并行下载。脚本会阻塞其后内容的呈现,还会阻塞其后面组件的下载。
HTTP1.1规范建议浏览器从每个主机名并行地下载两个组件,而HTTP1.0,Firefox的默认值是每个主机名并行下载8个组件。
研究表明:使用两个主机名比使用1,4或10个主机名能带来更好的性能。
在下载脚本时浏览器阻塞并行下载的另外一个原因是为了保证脚本能够按照正确的顺序执行。
规则七:避免CSS表达式
CSS表达式很容易导致频繁求值,从而导致性能低下。
避开问题: 1)、用一次性的表达式
2)、使用事件处理器代替。
规则八:使用外部的js和css
纯粹而言,内联快一些。但是外部的js和css文件有机会被浏览器缓存起来,而且可维护性也高得多。
两全其美的方法是加载后下载,即JS和css被加载到页面中两次(先是内联的,然后是外部的)。为主页内联css和js,但又能为后续页面浏览量提供外部文件。可以通过在主页加载完成后动态下载外部组件来实现。(通过onload时间)要使其能够工作,必须处理双重定义。(在onload函数内,添加外部的css和js,新增link和script标签到页面)
还可以利用cookie指示器来实现动态内联。用户第一个访问页面时,服务器发现没有cookie,则生成一个内联了组件的页面。然后服务器添加js来在页面加载后动态下载外部文件(并设置了cookie)。下一次访问页面,服务器看到了cookie,则会生成一个使用外部文件的页面。
规则九:减少DNS查找
Keep-Alive可以通过重用现有连接而避免了重复的DNS查找,还能避免TCP/IP开销来减少响应时间。
减少唯一主机名的数量就可以减少DNS查找的数量,但也会潜在的减少页面中并行下载的数量。
作者的建议是将页面的组件分别放到至少两个,但不要超过四个主机名下。
通过使用Keep-Alive和较少的域名来减少DNS查找。
规则十:精简js
精简是从代码中移除不必要的字符以减少其大小,进而改善加载时间的实践。
精简js代码的工具有JSMin,Compressor(已更名为ShrinkSafe)
Gzip压缩产生的影响最大,但精简能够进一步减少文件大小,随着js 的使用量和大小不断增长,精简js代码能够得到更多的节省。
CSS的精简也很有必要,移除注释和空白,合并相同的类,移除不适用的类以及进行一些直观的优化,比如对颜色进行缩写和移除不必要的字符串(用0代替0px)
规则十一:避免重定向
HTML文档的头中包含的meta refresh标签可以在其content属性所指定的秒数之后重定向用户
<meta http-equiv=”refresh” content=”0” url=http://stevesouders.com/newuri>
在URL结尾必须出现斜线(/)但没有出现时,会出现一次重定向(注意:当主机名缺少结尾斜线时则不会重定向)
对于内部流量的跟踪,可以通过建立Referer日志来避免重定向,以此节省最终用户响应时间。
对于跟踪出站流量,可以使用信标——一个HTTP请求,其URL中包含有跟踪信息。比如在a标签上添加点击事件,新建一个图片对象,给它的src赋予链接来源和出处。
规则十二:删除重复脚本
重复脚本损伤性能的方式有两种:不必要的HTTP请求和执行js所浪费的事件。
避免重复脚本:
1)、在模板系统中实现一个脚本管理模块。
2)、在PHP中建立一个称作insertScript的函数
规则十三:配置ETag
ETag是唯一标识了一个组件的一个特定版本的字符串,唯一的格式约束是该字符串必须用引号引起来。服务器会使用ETag响应头来指定组件的ETag。
Get /i/yahoo.gif HTTP1.1
Host:us.yimg.com
HTTP1.1 200 ok
Last-Modified:Tue,12 Dec 2006 03:03:59 GMT
ETag:”10c24bc-4ab-457e1c1f”
Content-Length:1195
如果浏览器必须验证一个组件,它会使用If-None-Match头将ETag传回到服务器,如果ETag是匹配的,就会返回304状态码。
ETag对于完全相同的组件,在不同的服务器上产生的ETag是不同的,所以如果你只在一台服务器寄宿网站,这不是什么问题,但如果你使用了服务器集群,则组件的下载可能比必须进行的下载次数还要多,导致了性能的下降。
而ETag还降低了代理缓存的效率,因为代理后面用户缓存的ETag经常和代理缓存的ETag不匹配,导致了不必要的请求被发送到服务器。
If-None-Match比If-Modified-Since有更高的优先级。
综合:从ETag中移除changeNumber或完全移除ETag可以避免当数据已经位于浏览器缓存中时进行不必要的和低效的下载,而且Last-Modified头可以提供完全等价的信息。
规则十四:使ajax可缓存
Ajax不是一个单独的,需要许可证的技术,而且一组技术,包括js,css,dom和异步数据获取,ajax 的目的是为了图片Web本质的开始-停止交互方式。
Ajax请求分被动和主动。被动请求:为了将来使用而预先发起的,比如:预加载。主动请求:基于用户当前的操作而发起的。
使ajax请求可缓存,可以使用一个长久的Expires头来替换原来的HTTP头,但还需要进行更多的工作,使用查询字符串参数,将用户名以及该消息的ID都加入查询字符串中。
要确保Ajax请求遵守性能知道,尤其应具有长久的Expires头。
其实也没有完全消化,还不太了解ajax缓存的具体实现方法,比如使用查询字符串参数这种方式,还望各位前端大神多多指教。
欢迎分享本文,转载请保留出处:前端ABC » 《高性能网站建设指南》笔记