• [存底]加速,加速,再加速:来自Google的网站加速技巧大全


    原文:http://developer.51cto.com/art/200906/132210.htm

    困扰许多网站所有者很久的一个问题是网站访问速度总是那么慢。想购买独立带宽,预算不允许,想购买CDN加速,价格又太贵。那有没有经济实惠的解决办法呢?从目前的大环境来分析,我们也只有通过技术手段来解决这个问题了。

    对Web开发有着深刻理解的著名搜索引擎厂商Google前段时间发布了一款Firefox /Firebug插件Page Speed(为 什么是Firefox 而不是Chrome?),并已开源,网络管理员和Web开发人员使用这个插件对Web页面的性能进行评估,并提供改善性能的有益建议。并于今日呼吁大家共 同努力,一起为互联网加速,可不是提什么空口号,Google已经将其研究结果和数据共享了出来,并提供了大量的网站加速教程,本文就对这些教程加以整 理,与诸位共勉

    css:每个声明只使用一次

    要想让你的网站速度更快,其中重要的一条就是发送到浏览器的客户端代码要尽可能小,在优化css文件时,一个重要的原则就是每个声明只使用一次。这样就可以严格使用选择器组合。

    例如,你可以将这两个规则

    1. h1 { color: black; } 
    2. p { color: black;  

    合并成一个规则

    1. h1, p { color: black; }

    这个例子是最简单的了,实际开发中的情况要复杂得多,根据我个人的开发经验,每个声明只使用一次后可以将css文件的大小降低20%-24%。下面再看一个复杂一点的例子:

    1. h1, h2, h3 { font-weight: normal; } 
    2. a strong { font-weight: normal !important; } 
    3. strong { font-style: italic; font-weight: normal; } 
    4. #nav { font-style: italic; } 
    5. .note { font-style: italic; }

    根据每个声明只使用一次的原则,将其缩减为

    1. h1, h2, h3, strong { font-weight: normal; } 
    2. a strong { font-weight: normal !important; } 
    3. strong, #nav, .note { font-style: italic; } 

    注意!important声明可以与众不同。

    在应用这个方法时有几点需要牢记于心:

    ◆ 首先,太长的选择器可能致使这个方法无效,重复选择器如html body table tbody tr td p span.example不能减少文件尺寸大小,实际上,每个声明只使用一次可能意味着选择器的数量会上升,甚至可能导致css文件更大,使用紧凑的选择 器是更有帮助的,并且可以提升样式表的可读性。

    ◆第二,小心css规则,当一个用户代理不能解析选择器时,必须忽略声明,当你遇到这种情况时,只需要修改一下规则,让其可以使用多次即可。

    ◆第三,也是最重要的一点,如果你对样式表进行了排序,这个原则会改变你的排序,但这个顺序可以由浏览器来决定,如果你使用这种方法运行出了问题,最好的解决办法就是产生一个异常,并在出现问题的地方让声明使用多次就可以了。

    在使用一个声明只使用一次的方法维护样式表时要格外小心,可以通过优秀的编辑器来跟踪变化(如显示变化行),然后在需要的地方插入声明,这种做法需要合并到工作流中。其实一个有效的方法是使用缩进排版,这样就很容易发现重复的声明的了。

    使用gzip压缩页面

    Gzip 压缩需要Web服务器的支持,在没有gzip压缩的情况下,Web服务器直接把html页面发送给浏览器,而支持gzip的Web服务器将把html压缩 后再发给浏览器,支持gzip的浏览器再在本地进行解压和解码,并显示出来。Gizp会将css文件,js文件,html文件中那些重复的字符串、标签、 空格和样式定义进行压缩。我们还是举一个例子加以说明。

    下面的代码未压缩前69字节,压缩后85字节。

    1. < h1>One< /h1> 
    2. < h2>Two< /h2> 
    3. < h3>Three< /h3> 
    4. < h4>Four< /h4> 
    5. < h5>Five< /h5> 

    我们将标题标签替换成div标签,源代码大小增加了10字节,变成了79字节,但经过压缩后只有66字节。

    1. < div>One< /div> 
    2. < div>Two< /div> 
    3. < div>Three< /div> 
    4. < div>Four< /div> 
    5. < div>Five< /div> 

    HTTP缓存

    如果你正确设置了HTTP缓存报头,不但Web页面载入速度更快了,而且Web服务器的负荷也减少了,是一个双赢的举措。

    缓存也就是资源的本地副本,因为很多资源都不会频繁更新,这时浏览器就可以直接从本地获取资源,不用到服务器去取,节省了连接时间和资源下载时间,使用HTTP缓存真正起关键作用的是HTTP缓存报头,这个报头指定了资源的有效时间和最后修改时间。

    http 协议有两种方法定义资源的有效时间:Expires和Cache-Control: max-age报头。Expires报头指定资源的过期日期,而max-age指定的是当资源下载到本地后多长时间有效。实际上它们要表达的最终含义是一 致的。建议将资源的有效日期指定为1个月,长一点的话可以指定为1年。这两个报头一般只需要设置一个即可,如果同时进行了设置,那么max-age的优先 级比Expires要高一些。如果你的资源比这个设定期限更新得要频繁一些,那么你可以采取对资源重新命名的方法,通常的做法是在URL中给资源加上版本 号,当然这是引用资源的html页面也得做对应的修改。

    当本地资源是有效状态时,浏览器有两个选择,其一是全部重新下载所有资源,其二是仅下载有变化的资源,为了让浏览器只下载有变化的资源,我们需要在GET请求中加上条件,http协议给了我们两个选项:Last-Modified和ETag报头。

    Last-Modified报头指资源的最后修改时间,ETag报头是每个资源不同版本的唯一身份识别号,我们推荐你使用Last-Modified报头,因为日期如果足够早,浏览器可以跳过请求全部资源的。下面是两个测试页。

    关闭Expires

    开启Expires

    在第二次载入页面时,可以再次点击链接,或者在地址栏中再按一次回车,如果点击刷新按钮,如果资源还在缓存中的话,会强制浏览器重新使用附条件的GET请求去获取资源。

    为了更清晰地看到这个完整过程,可以使用HttpWatch工具,它可以查看http报头。如果使用Apache的话,可以参考mod_expires模块的资料。

    使用Page Speed提升网站性能

    Page Speed是由Google发布了一款开源Firefox 插件,它可以评估Web页面的性能问题,并能够给出合理的优化建议,同时它也可以将资源变得更小。

    ◆图片压缩

    图片文件中通常都包含了一些额外的信息,如JPEG图片包括创建图片所用工具的信息,PNG图片通过创新编码可以缩小文件大小,这些转换都是无损的,压缩后的图片和未压缩的图片看起都是一样的,但占用的字节数却少了,

    Page Speed使用优化图像功能尝试为页面中的所有图片进行无损压缩,如果成功的话,就显示压缩后的版本,为了使用图片的最低版本,在Page Speed面板中点击链接到压缩版本,保存,使用它代替原始图片。

    ◆削减JavaScript

    移 除大型JavaScript文件中的注释和空格可以大幅度减少文件的尺寸,但功能却无丝毫损伤。Page Speed提供了削减JavaScript的功能,削减成功后Page Speed会显示一个到该文件的链接,如果要使用削减后的文件,点击那个链接,保存文件,然后到html页面中重新引用这个更小的JavaScript文 件。

    但这样做有一个问题,削减后的JavaScript文件的移动性就降低了,如果你经常更新的话,建议你使用另一个削减命令行工具JSMIN。

    ◆移除不用的css

    移除css文件没有使用到的规则将有助于减少css文件的大小,因为浏览器在浏览Web页面时往往会将css文件下载到本地,这样就可以减少发送到浏览器的信息量,从而加速页面反应速度,但值得注意的是,有些外部css文件是由多个Web页面引用的,在移除时要特别小心。

    Page Speed提供了移除不同的css功能,它可以告诉你那些css规则是没有被使用的。

    除了上面提到的这三个功能外,Page Speed还有更多的功能等待你去发掘。

    减少浏览器reflow

    Reflow 是浏览器为重新渲染文档或文档中的一部分,重新计算文档元素的位置和几何大小的统称,因为reflow在浏览器中是一个用户拦截操作,这对于开发人员理解 如何提升reflow时间和不同文档属性(DOM深度、css规则效率、不同类型的样式变化)对reflow时间的影响。有时reflow一个元素可能需 要reflow文档中的所有元素,以及跟着它的所有元素。

    有很多中用户行为和DHTML变化可以触发reflow,如改变窗口大小、使用包 含计算样式的JavaScript函数、从DOM中添加或移除元素以及改变某个元素的类别都可以触发reflow,值得注意的是有些行为可能导致 reflow的时间比你想象中的要多。来看一张图。

    主流浏览器reflow时间对比
    图- 1 主流浏览器reflow时间对比

    从上图可以看出不是JavaScript中任何样式的变化都会触发reflow,还可以看出浏览器版本越高reflow时间更好了。

    在Google,我们对我们的页面进行了大量的测试,最终我们认为要往页面中添加UI元素时最值得考虑的因素就是reflow时间了。下面是我们整理的可以帮助减少reflow时间的方法:

    ◆减少不必要的DOM深度,在DOM树上任意一层发生的变化都会影响到DOM树的所有层,当然这在reflow时花的时间肯定比较多了。

    ◆缩小css规则,移除不用的css规则。

    ◆如果你使用更复杂的演示变化,如动画,那么你最好使用绝对位置或将位置固定下来。

    ◆避免不必要的复杂的css选择器,特别是衍生选择器,它需要更多的CPU时间处理选择器匹配。

    优化JavaScript代码

    客户端代码可以让你的应用程序动起来变得更有活力,但这些代码可能使浏览器变得更低效,不同的客户端性能也不一样,这里我们讨论几个优化JavaScript的技巧。

    ◆字符串的使用

    在IE6和IE7中因字符串级联导致的主要问题是垃圾回收性能,虽然这些问题在IE8中已经得到解决,但如果你的用户大部分仍然在使用IE或IE7,你就得格外注意这个问题了。看一个例子先:

    1. var veryLongMessage = 
    2. 'This is a long string that due to our strict line length limit of' + 
    3. maxCharsPerLine + 
    4. ' characters per line must be wrapped. ' + 
    5. percentWhoDislike + 
    6. '% of engineers dislike this rule. The line length limit is for ' + 
    7. ' style purposes, but we don't want it to have a performance impact.' + 
    8. ' So the question is how should we do the wrapping?';

    ◆使用连接代替级联:

    1. var veryLongMessage = 
    2. ['This is a long string that due to our strict line length limit of', 
    3. maxCharsPerLine, 
    4. ' characters per line must be wrapped. ', 
    5. percentWhoDislike, 
    6. '% of engineers dislike this rule. The line length limit is for ', 
    7. ' style purposes, but we don't want it to have a performance impact.', 
    8. ' So the question is how should we do the wrapping?'
    9. ].join();

    与此类似,在条件语句中使用级别也是很低效的,错误的做法:

    1. var fibonacciStr = 'First 20 Fibonacci Numbers 
    2. '; 
    3. for (var i = 0; i <  20; i++) { 
    4. fibonacciStr += i + ' = ' + fibonacci(i) + ' 
    5. '; 
    6. }

    正确的方法:

    1. var strBuilder = ['First 20 fibonacci numbers:']; 
    2. for (var i = 0; i <  20; i++) { 
    3.   strBuilder.push(i, ' = ', fibonacci(i)); 
    4. var fibonacciStr = strBuilder.join('');

    ◆定义类函数

    下面的函数是低效的,因为每次构造baz.Bar的实例时,会创建一个新的函数和闭包:

    1. baz.Bar = function() { 
    2.   // constructor body 
    3.   this.foo = function() { 
    4.   // method body 
    5.   }; 

    正确的方法是:

    1. baz.Bar = function() { 
    2.   // constructor body 
    3. }; 
    4.  
    5. baz.Bar.prototype.foo = function() { 
    6.   // method body 
    7. }; 

    使用这个方法时,无论baz.Bar构造了多少个实例,都只会为foo创建一个函数,而且不会创建闭包。

    ◆初始化实例变量

    使用实例变量值类型初始值初始化实例变量声明,如数值、布尔值、空值、未定义或字符串,这样可以避免每次调用构造器时运行不必要的初始化代码。还是来看一个例子:

    1. foo.Bar = function() { 
    2.   this.prop1_ = 4; 
    3.   this.prop2_ = true
    4.   this.prop3_ = []; 
    5.   this.prop4_ = 'blah'; 
    6. }; 

    可以使用:

    1. foo.Bar = function() { 
    2.   this.prop3_ = []; 
    3. }; 
    4.  
    5. foo.Bar.prototype.prop1_ = 4; 
    6.  
    7. foo.Bar.prototype.prop2_ = true
    8.  
    9. foo.Bar.prototype.prop4_ = 'blah'; 
    10.  

    进行代替。

    ◆避免使用with

    避免在代码中使用with,它会影响到性能,因为它修改了范围链,因此需要花费更多时间到其它范围去查找。

    ◆避免浏览器内存泄漏

    对 于Web应用程序而言,内存泄漏是很常见的事情,可能因此导致巨大的性能问题。因为浏览器的内存使用在增长,你的Web应用程序和其它程序就会变慢,最常 见的内存泄漏是在JavaScript引擎和浏览器C++对象实现的DOM之间形成了循环引用,如在JavaScript引擎和IE浏览器的COM基础结 构之间,以及JavaScript引擎和Firefox  XPCOM基础结构之间。

    优化网页图片

    当你在优化网页代码时,别忘了那些静态内容,包括图片,经过简单的优化就可以大大减少下载大小,并且也不会降低网站的质量。

    我们总结了一些技巧,可以帮助你加快网页图片的载入速度:

    ◆剪裁掉多余的空白

    剪裁掉多余的空白
    图- 2 剪裁掉多余的空白

    如果确实需要空白内边距,可以使用css代码来实现。

    ◆使用最佳的文件格式

    可以通过一些专业的图片处理工具,如photoshop就可以直接保存为网页图片,如果将图片颜色从256色调整到32色,那文件大小会明显变小,下面来看看一张图片不同文件格式时的大小对比。

    示例图片
    图- 3 示例图片

    上面这张图片不同文件格式时的大小对比结果如下:

    ◇JPG, 60 quality - 32K

    ◇PNG-8, 256 colors - 37K

    ◇GIF, 256 colors - 42K

    ◇PNG-24 - 146K

    由于8位png和gif格式相对而言图像质量不错,文件大小更小,因此在网页中建议多使用这两种格式。

    PHP性能技巧

    51CTO编辑注:对于以下这部分内容,PHP小组已发布公开信反驳,其中的有些建议究竟是否正确还有待进一步研究。

    由于PHP的使用量非常大,所以有必要放在这里说一说。首先有一点需要阐明的是,网站的性能与PHP版本,Web服务器环境和代码的复杂度都是有关的。

    ◆升级PHP版本

    首先要做的是升级PHP版本,如果你还在使用PHP3或PHP4,那赶快升级吧!

    ◆使用缓存

    使用缓存模式,如memcached,可以将数据库查询结果或网页缓存起来,加快Web服务器的响应速度。

    ◆使用缓冲输出

    PHP使用内存缓冲存储你的脚步尝试打印的所有数据,这个缓冲看起来好像让你的网页变慢,因为用户必须等待缓冲被填满,幸运的是,你可以做一些修改强制让PHP快速清空输出缓冲。

    ◆没有原因尽量不要复制变量

    有些PHP新手试图通过拷贝预先定义的变量使代码变得清晰,但事实是这样会导致双倍的内存消耗。我们来看一个例子,假设有个不怀好意的用户向文本区域插入了512KB的内容,那么会使用1MB内存:

    1. $description = strip_tags($_POST['description']); 
    2. echo $description; 

    上面这个例子就是没有原因的拷贝变量,其实可以简化它,避免额外的内存消耗:

    1. echo strip_tags($_POST['description']); 

    ◆避免在循环中执行SQL查询

    一个常犯的错误是在循环中使用SQL查询,这样会引起多次数据库往返,降低脚本速度,在下面的例子中,你可以修改循环构建一个SQL查询,一次性插入所有的用户:

    1. foreach ($userList as $user) { 
    2.   $query = 'INSERT INTO users (first_name,last_name) VALUES("' . $user['first_name'] . '", "' . $user['last_name'] . '")'; 
    3.   mysql_query($query); 
    4. }

    改为:

    1. INSERT INTO users (first_name,last_name) VALUES("John", "Doe") 

    不用循环,你可以合并成一次数据库查询:

    1. $userData = []; 
    2. foreach ($userList as $user) { 
    3.   $userData[] = '("' . $user['first_name'] . '", "' . $user['last_name'] . '")'; 
    4. $query = 'INSERT INTO users (first_name,last_name) VALUES' . implode(',', $iserData); 
    5. mysql_query($query);Produces: 
    6. INSERT INTO users (first_name,last_name) VALUES("John", "Doe"),("Jane", "Doe")...

    ◆为长字符串使用单引号

    PHP允许对字符串变量封装同时使用单引号和双引号,但是是有区别的,使用双引号时,告诉PHP引擎读取字符串内容并查找变量,然后使用它们的值替换它们,对于一个很长的但没有包含变量的字符串,将导致性能下降。

    ◆使用switch/case替代if/else

    使用switch/case比使用if/else性能更好,易读性和易维护性也更佳。

    预取资源

    预取资源就是当用户还没有请求该资源就预先下载到本地,那当用户真正请求时,可以大大减小网络延迟时间,甚至消除网络延迟时间。

    对于交互式网站,优化速度不仅仅是减小初始下载大小,当用户交互时可以下载额外的资源,这些行为的速度依赖于下载这些资源的时间,将下载资源变小可以加快网站速度。在设计预取资源时要考虑以下几个问题:

    ◆研究用户行为

    如果你的用户在某个特定的页面或行为上花费了大量的时间,那这就是你该优化的,你可以通过查找服务器日志来找出这些页面和行为。对于picasa网络相册,我们知道最多的操作是一张张浏览图片,那么这就是非常合适的预取对象。

    ◆衡量网页准好的时间

    在当前页面没有显示完时不应该提取新页面的数据,对于动态页面,你需要为页面上每个外部文件添加JavaScript载入处理程序,当这些资源全部下载下来后,为用户下一个行为预取数据就非常合理了。

    ◆使用工具测试

    在正式修改代码前,先用Page Speed这类工具进行测量,要避免一次提取太多数据造成网站变慢。

    适当的包含样式和脚本

    网页载入时间一般80-90%的时间都花在等待网络上了,最有力的方法是消除序列化下载资源。

    联合外部JavaScript文件

    下载外部脚本文件时一般浏览器会等它下载完了再继续后面的下载,这与并行下载图片的行为是完全相反的。

    例1:两个外部脚本文件

    例2:两个外部图片

    在例2中,两个需要1秒的图片合在一起时,总共也只需要1秒就完成下载了,在例1中,两个需要1秒的脚步合在一起时,却需要2秒才能完成下载,这是两个不同的并行和串行下载。因此,如果你有多个外部脚本文件,最好将它们合并到一个文件中。

    在外部JavaScript文件前包含额外的css文件

    由于脚本文件会阻止后面的下载,那些已经在下载中的将会继续下载。

    例3:在css之前的脚本

    例4:在脚本前的css

    在例3中,脚本在css文件前会导致浏览器堵塞,要花2秒时间,但只需要将css移到脚本前面就可以让下载过程并行执行,如例4。因此,如果你既有外部css文件,又有外部脚本文件,那么记住一定要将css文件放到脚本文件的前面。

    在外部css和其它资源之间不包含内联JavaScript

    使用内联脚本标签时,即使它没有下载任何东西,也会阻碍后面的下载。

    例5:css后的内联脚本

    例6:css前的内联脚本

    例5中内联脚本块位于样式和脚本之间,下载时是串行的,在例6中,移到样式前面后,再一次恢复到并行下载模式。因此,如果你有一个外部css文件,不要在你的css文件和下一个下载的资源之间插入内联脚本标签。

    减小HTML文档的文件大小

    想要减少网站的载入时间最佳的办法就是减小HTML文件的大小,有很多种办法可以实施,首先我们看看html哪些标签是可以瘦身的。

    ◆HTML 4

    根据HTML 4 DTD标准,可以有很多标记都省略掉,下面以斜体表示的标记都可省略掉:

    < /area>

    < /base>

    < body>

    < /body>

    < /br>

    < /col>

    < /colgroup>

    < /dd>

    < /dt>

    < head>

    < /head>

    < /hr>

    < html>

    < /html>

    < /img>

    < /input>

    < /li>

    < /link>

    < /meta>

    < /option>

    < /p>

    < /param>

    < tbody>

    < /tbody>

    < /td>

    < /tfoot>

    < /th>

    < /thead>

    < /tr>

    例 如,如果你有标记为< li>List item< /li>的列表项目,那么你可以将其省略为< li>List item,在表示段落结束时一般使用< /p>标记,但这下也可以使用< p>My paragraph了,这种省略语法对html、body、head都有效,在html中它们不是必须的。这样一通省略后,往往可以使整个html文件大 小减小5-20%。

    ◆HTML 5

    虽然HTML 5仍然在开发阶段,它向你提供了更多减小文件大小的选项。例如。HTML 5允许你象下面这样设置文档类型:

    1. < !DOCTYPE html> 

    相对

    1. < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 

    你 会注意到HTML 5 DTD更短了。当你指定文档的编码时,HTML 5更易于使用,并且更轻巧了,< meta charset="utf-8">和< meta http-equiv="content-type" content="text/html; charset=utf-8">表示的含义是一样的,浏览器一看也是知道要处理HTML。

    在HTML 5中另一个值得一提的是可以省略掉与MIME类型关联的类型属性了,这些属性如type="text/css"或type="text /javascript"描述了内容的类型,现在可以使用< script>代替< script type="text/javascript">,使用< style>代替< style type="text/css">。

    如果你将上面这些方法集合起来使用,将会节约10-20%的文件大小。请浏览Google的隐私页面,它就全部采用了这些方法。

    UI消息和感觉等待时间

    对于很多用户而言,速度并不等于性能,用户对一个网站的速度感觉会受到他们的总体体验影响,包括他们是否能够有效地获取到想要的内容,以及系统是如何人响应的。

    在设计你的网站时,要考虑用户访问该站点的目的是什么,越快(越容易)完成访问网站越好,如果用户在获得内容时遇到了很多困难,他们在完成任务后肯定会马上离开你的站点,并可能再也不愿意回来。

    其实要让用户觉得网站使用起来感觉很舒服,你有很多事情要做,这里只讨论3个主题。

    1. 网站设计是否足够简单,即使是第一次使用该网站的用户也能够顺利地找到他们想要的内容。要达到开箱即用的效果。你可以花10天时间来考虑界面流程如何优化,这样对于10万用户而言,节省的时间和价值都大多了。

    2. 某个消息会打断或增加用户工作步骤吗?

    3. 用户在等待期间该做点什么?例如显示进度条,注意不要把进度条本身设计得过于庞大,一般建议使用“正在上传......”,“载入中.......”等等这样的纯文本就可以了。

    小结

    本文列举了12类加速网站的办法,在实际工作,可以视具体情况灵活运用,当你完全掌握了这些方法后,也许会触类旁通,引起你深入地追寻更深层次的加速办法。

  • 相关阅读:
    三元运算,列表解析,生成器表达式
    迭代器补充
    迭代器协议和for循环工作机制
    文件seek方法的补充
    文件操作的其他方法
    文件操作b模式
    文件操作的其他模式
    其他内置函数
    [TimLinux] JavaScript table的td内容超过宽度缩为三个点
    [TimLinux] JavaScript BOM浏览器对象模型
  • 原文地址:https://www.cnblogs.com/gotolnc/p/1543876.html
Copyright © 2020-2023  润新知