XuGang

记录一个程序员的成长

 

《高性能网站建设指南》笔记


查看网站排名 http://www.alexa.com
HTTP规范    
http://www.w3.org/Protocols/rfc2616/rfc2616.html

HTTP协议的学习,推荐看David Gourley、Brian Totty编著的《HTTP: The Definitive Guide》一书。

 

绪言A

下载缓存图片:一个图片的HTTP请求默认是一个条件GET请求(Conditional  GET  request)。
例如:
......
If-Modified-Since: Wed, 22 Feb 2006 04:15:54 GMT

Live HTTP Headers 是一个查看HTTP请求信息的Firefox插件。

下载地址:https://addons.mozilla.org/zh-CN/firefox/addon/3829
官方地址:http://livehttpheaders.mozdev.org/installation.html

 

绪言B

压缩:在一个HTTP请求中,可以使用压缩来减小响应的大小。
浏览器端:Accept-Encoding: gzip,deflate
服务器端:Content-Encoding: gzip

 

规则1 ------ 减少HTTP请求

方案:

A  图片地图
    <img   usemap="#myname" ....>

    <map  name="myname">

 

B CSS Sprites

    示例:http://stevesouders.com/examples/sprites.php

 

C  内联图片

内联图片是将简单图片的编码数据直接保存在URL自身之中。(需要内联编码技术)

格式:data: [<mediatype>][;base64],<data>

例如:<img  src="data: image/gif; base64,FNMSDAAAAA......"



规则2 ------ 使用内容发布网络

 

内容发布网络(CDN):是一组分布在多个不同地理位置的Web服务器,用来存储静态文件(多数情况)以保证响应速度的提高。

比较著名的CDN服务提供商有:Akamai,Mirror Image,SAVVIS等。


规则3 ------ 添加Expires头

 

<!-- expires 表示网页在浏览者计算机缓存中的过期时间 -->
<meta  http-equiv="expires"  content="Wed, 26 Feb 1997 08:21:57 GMT">

<!--  使用带有max-age的cache-control指定组件被缓存多久 -->
<meta  http-equiv="cache-control"  content="max-age=315360000">

注意:
1.  Cache-Control 具有优先权于Expires
2.  为了确保更新的组件在用户的浏览器中也更新(而不是使用缓存中的),解决方案是:将所有需要更新的组件更改文件名。


规则4 ------ 压缩组件

 

客户端通过HTTP请求的Accept-Encoding头来标识对压缩的支持。

Accept-Encoding:  gzip, deflate

注意:   

      推荐使用 gzip (最流行,最有效)

      压缩对象:HTML、CSS、JS、XML、JSON 等任何文本。

      不压缩对象:图片、PDF文件。(它们已经被压缩过,再压缩的话,会耗费CPU资源,甚至加大文件的大小)


规则5 ------ 将CSS样式表放在顶部

将CSS样式表放在页面底部,会导致在浏览器中阻止内容的逐步呈现。
原因:浏览器为了避免当样式变化时重绘页面中的元素,浏览器会阻塞页面内容的逐步呈现,直到样式表下载完毕之后再呈现它们。

将CSS样式表放在底部会降低呈现速度(而不是下载速度)。所以,我们应该将CSS放在顶部<head>标签中。

链接CSS样式表有两种方式:
方式一<link  rel="stylesheet"  href="styles1.css">

方式二:
<style>
@import  url("styles1.css");
</style>

注意:
  1.  使用@import方法必须放在<style>标签的顶部。
  2.  即使@import方法放在了<head>标签中,它所指定的样式表文件却依然是最后下载的。

所以,不推荐使用@import方法加载CSS样式表,而推荐使用<link>标签将CSS样式表放在文档的<head>中。


规则6 ------ 将脚本放在底部

将脚本放在页面顶部:
-- 脚本会阻塞对其后面组件的下载;
-- 脚本会阻塞对其后面内容的呈现;

 

示例:http://stevesouders.com/hpws/js-top.php

    <!-- 截取代码 -->
    <html>
    <head>
    <!-- 使用script调用相关代码并传入相关参数 -->
    <script src="/bin/sleep.cgi?type=js&sleep=10&expires=-1&last=0"></script>
    <title>Scripts at the Top</title>

最好将脚本从页面的顶部移到底部(如果可以的话)。这样页面既可以逐步呈现,又可以提高下载的并行度。
使用脚本时,对于所有位于JS脚本以下的内容,逐步呈现都将被阻塞。

 

HTTP 1.1规范中,建议浏览器从每个主机并行地下载2个组件。

如果一个Web页面平均地将其组件分别放在2个主机下,就可以并行下载4个组件,整体响应时间将可以减少大约一半。
示例:
    <!-- 将JS代码的引用放在页面底部 -->
    <script src="/bin/sleep.cgi?type=js&sleep=10&expires=-1&last=0"></script>
    </body>
    </html>

延迟(Defferred)脚本:
defer属性表明脚本不包含document.wirte语句,浏览器得到这一线索就可继续进行呈现。
但只IE支持,而Firefox不支持该<script>的defer属性。
示例:
    <html>
    <head>
    <!-- 在script中使用defer属性 -->
    <script src="/bin/sleep.cgi?type=js&sleep=10&expires=-1&last=0" defer></script>
    <title>Deferred Scripts</title>

注意:如果一个脚本可以延迟,那么它一定可以移到页面的底部。
         将脚本移到页面底部才是加速Web页面的最佳方式!


规则7 ------ 避免CSS表达式

原因:
1.  CSS表达式用于动态设置CSS属性,它只受到IE 5及以后版本的支持。
2.  禁用CSS表达式,因为它几乎在触发各种事件时都会被调用。
3.  有的时候,CSS表达式也会影响页面的加载时间。

CSS表达式(示例):
background-color: expression( (new Date()).getSeconds()%2 ? "red":"blue" );
详细实例:
<HTML>
<HEAD>
<style>
.mybody{
  background-color: expression((new Date()).getSeconds()%5 ? '#FF0000':'#0000FF');
  }</style>
</HEAD>
<BODY class="mybody"></BODY>
</HTML>

IE不支持min-width属性,所以在IE中使用CSS表达式。
width:expression(document.body.clientWidth<600? "600px":"auto");
min-width:600px;

注意:禁用CSS表达式,因为它几乎在触发各种事件时都会被调用。

改进:(一次性表达式)
<style>
P{  background-color: expression( altBgcolor(this) ); }
</style>
<script  type="text/javascript">
  function  altBgcolor(elem)
  {
elem.style.backgroundColor=(new Date()).getHours()%2 ?"#f00":"#0f0";
  }
</script>

在调用JS代码后,JS代码重写了其background-color属性,所以只会执行一次。


规则8 ------ 使用外部CSS和JS

纯粹而言,内联CSS和JS要快一些。但外部CSS和JS文件有机会被浏览器缓存起来。当一个页面被重复访问时,就不需要重复下载外部CSS和JS了。

你的网页究竟是使用外部还是内联的CSS和JS?
这个问题要根据你网页的实际情况而定。
关键点在于:
1.  页面查看的数量
2.  页面缓存(空缓存 VS 完整缓存)
3.  组件(CSS或JS)的重用率。即:该外部文件在别的页面是否被重用。

加载页面后下载组件(本人不推荐)
示例:
<script>
function  doOnLoad()
{
   setTimeout("downComponents()", 1000);
}
window.onload = doOnLoad;

function  downComponents()
{
    downJS("http://stevesouders.com/examples/testsma.js");
    downCSS("http://stevesouders.com/examples/testsm.css");
}
function downJS(url)
{
    var  elem = document.createElement("script");
    elem.src = url;
    document.body.appendChild(elem);
}
function downCSS(url)
{
    var  elem = document.createElement("link");
    elem.rel = "stylesheet";
    elem.type = "text/css";
    elem.href = url;
    document.body.appendChild(elem);
}
</script>


规则9 ------ 减少DNS查找

DNS:Domain  Name  System

TTL值(Time - to - live,生存时间):
每个记录都有一个生存时间(TTL)值,这个值就决定了这个纪录什么时候刷新,进而被其他查询取代。在TTL到达之前,Windows解析将返回缓存中的查询结果,而不会开始新的DNS查询。

DNS  Client  服务 -- --> 在操作系统客户端的配置:
可以使用控制台的IPConfig 命令来观测缓存容量并清空缓存。

通过以下的命令就可以显示缓存的容量,并将结果传送给More指令,从而将结果一次性在一页中显示出来:ipconfig /displaydns | more
使用一下这个命令来清空缓存:ipconfig /flushdns
要停止 DNS 缓存,请运行下列任一命令:net stop dnscache

浏览器自身也有其DNS缓存(如:IE、Firefox),而它们的配置要在注册表中修改。
每次重新启动浏览器也就自动清空了浏览器的DNS缓存,但它不会清空DNS  Client  服务缓存。

Fasterfox(http://fasterfox.mozdev.org)是一款Firefox的插件,用于测量和改善Firefox的性能。


规则10 ------ 精简JavaScript

精简JavaScript代码的最流行的工具是:JSMin软件
http://www.crockford.com/javascript/jsmin

Command Line Options
命令行选项

Optional parameters will be listed at the beginning of the output as comments. This is a convenient way of replacing copyright messages and other documentation.
任意参量在产品初将是列出的作为评论。 这是替换版权消息和其他文献一个方便方式。

Example:
    jsmin <fulljslint.js >jslint.js "(c)2002 Douglas Crockford"

Dojo ShrinkSafe软件:能够移除JavaScript代码中的大部分空白,同时还缩短了变量名。
http://www.dojotoolkit.org/downloads

注意:混淆代码也能够移除注释和空白,同时还会改写代码,实现代码的加密码工作。
        但混淆代码很有可能在混淆过程中引入错误,难以调试。(不推荐使用混淆代码)

对一个网页进行gzip压缩产生的影响最大,但精简代码能进一步减小文件。
精简CSS最大的潜在节省来自:合并相同的类、移除不使用的类、移除注释和空白,并进行一些直观的优化。如:缩写(用"#606"代替"#660066"),移除不必要的字符串(用"0"代替"0px")。


规则11 ------ 避免重定向

重定向(Redirect)用于将用户从一个URL重新路由到另一个URL,它会使你的页面变慢。

重定向有很多种,“301 Moved Permancenty”和“302 Moved Temporarily (也叫 Found)”是最常用的两种。

有一种重定向很频繁和浪费,那就是URL的结尾必须出现斜线(/)而没有出现时。
例如:
http://www.cnblogs.com/xugang 这个请求将导致一个301重定向到http://www.cnblogs.com/xugang/ (唯一的区别就是结尾添加了斜线)。

而http://www.cnblogs.com 不会导致重定向,尽管你最终看到的是http://www.cnblogs.com/也不会,因为它会简单的使用文档根(/)。


跟踪站内流量:使用Referer日志(也被叫做:referrer)可以跟踪网站流量的去向。
跟踪出站流量:使用信标(beacon)可以在HTTP请求的URL中包含跟踪信息。

美化URL有两种方式:
    1、使用URL重定向;
    2、使用代码和Web服务器端的配置进行设置。


规则12 ------ 移除重复脚本

导致重复脚本的因素:团队大小和脚本数量。
避免重复脚本的一种方法是:实现一个脚本代码管理模块(用javascript编写避免重复加载.js文件的代码)。

注意:javascript代码文件一旦改变,其文件名也要更改。(最好在其文件取名中包含该文件的版本编号,如:menu_1.1.js)


规则13 ------ 配置ETag

ETag:实体标签(Entity Tag),是Web服务器和浏览器之间用于确认缓存组件的有效性的一种机制。
ETag是唯一标识了一个组件的一个特定版本的字符串(该字符串必须使用引号)。

注意:
      其“实体”是页面“组件”的另一种称呼。
      当一个网站被宿主在多于一台服务器上时,ETag头可能会阻碍缓存。

 

检测组件是否有效时,是通过Web服务器与客户端缓存的组件进行匹配的。有两种方式:

    -- 比较最新修改日期
    -- 比较ETag实体标签

服务器传递客户端组件一个ETag,如:
    服务器发送   ETag:"10c24bc-4ab-457e1c1f"

此后,如果浏览器验证该组件,则会使用If-None-Match头将ETag传回原始服务器,如:
    浏览器发送   If-None-Match:"10c24bc-4ab-457e1c1f"

如果相同,则服务器返回   304 Not Modified
如果不相同,则服务器重新向浏览器发送该组件。

如果一个网站有多台服务器,那么,对于完全相同的组件,从一台服务器到另一台服务器,Apache和IIS产生的ETag是不会匹配的。

建议ETag只用在单个服务器的网站上,如果网站使用的服务器集群,ETag将导致性能的下降。

ETag的服务器返回(If-None-Match)比最新修改日期的返回(If-Modified-Since)具有更高的优先级。如果同时存在,则会禁止返回 304 Not Modified。

在多服务器的网站上,除非你修改ETag格式(如:IIS中实现从ETag中移除ChangeNumber,只留时间戳),否则最好将ETag完全移除,已避免组件的重复下载。

如何在IIS中移除ETag,参考:
http://support.microsoft.com/?id=922733
http://support.microsoft.com/?id=922703

从ETag中移除ChangeNumber或完全移除ETag可以避免当数据已经位于浏览器缓存中时进行不必要的和低效的下载。


规则14 ------ 使Ajax可缓存

Ajax除了使用XML外,还能使用JSON实现。

Ajax的核心是XMLHttpRequest

可以使用Yahoo! UI(YUI)Connection Manager(http://developer.yahoo.com/yui/connection)来进行Ajax开发。它处理了XMLHttpRequest的浏览器兼容问题,并具有优秀的文档和代码示例。

网页抓包工具:IBM Page Detailer

SSL(Secure Sockets Layer):安全套接字层。

Google提供了一个Ajax的电子表格http://docs.google.com/

Ajax请求不是可缓存的,为了确保Ajax请求的性能,更应该添加长久的Expires头。

 

 

规则实践 ------ 析构十大网站


YSlow是Yahoo!开发的一个性能工具(http://developer.yahoo.com/yslow)。

YSlow还提供了JSLint工具(http://jslint.com)对页面中所有的JavaScript进行分析。

页面分析工具:Firebug(http://www.getfirebug.com),它已经集成了Yahoo!的YSlow工具。

Http请求图表:使用IBM Page Detailer生成,是一个比较好的抓包工具。http://alphaworks.ibm.com/tech/pagedetailer

响应时间的测量:使用的是Gomez的Web监视服务。http://www.gomez.com

PNG图片优化器:推荐使用PngOptimizer(http://psydk.org/PngOptimizer.php)

使用IFrame提供广告:
优点:如果广告中含有JS,则将其放到IFrame中就等于放到了沙箱中,无法访问该主页面的空间,可以带来安全性。
缺点:每个IFrame都带来了一个额外的HTTP请求。
      通常情况下,IFrame是不可缓存的。

注意:在HTTP 1.1中,每个主机名只有两个组件能够并行下载。

脚本会阻塞并行下载(同时出现在Firefox和IE中);

样式表也会阻塞并行下载(仅出现在Firefox中);

 

posted on 2009-12-10 11:53  钢钢  阅读(2211)  评论(2编辑  收藏  举报

导航