永利酒店赌场从雅虎军规看前端性能优化

Web性能优化系列 – 通过提前获取DNS来提升网页加载速度

2015/04/23 · HTML5 ·
DNS,
性能优化

本文由 伯乐在线 –
刘健超-J.c
翻译,sunbiaobiao
校稿。未经许可,禁止转载!
英文出处:www.deanhume.com。欢迎加入翻译组。

我时常寻找方法改善网站性能,为的就是能提供更佳的用户体验。也许你经常会发现你的网站运行高效且性能优异。你也可能曾让你的应用程序在Google
PageSpeed或Yahoo!
YSlow进行测试,并得到高分。然而,有一样东西一直影响页面加载时间。它在一个页面上,花费很多时间去查找不同组件的DNS。例如,下面这幅图片展示了我的博客首页所需资源的加载瀑布图。

永利酒店赌场 1

请注意条形图的灰蓝色部分,它出现在瀑布图中的大部分组件前。这灰蓝色代表下载资源前查找DNS所需时间。这竟然占了组件下载时间的很大部分!即使组件进行了优化,并已经最小化/合并/压缩处理,你仍然需要等待查找DNS时间。我利用webpagetest.org做了一个关于该网站DNS查找时间的表格。

永利酒店赌场 2

从上图可看到,DNS查找时间都很高,
如果能减少该时间并提速,便会让资源加载变得更加高效。幸运的是,有个很棒的技巧能让网站的加载时间变得更快。它被称为DNS预取,并且很容易实现。你所需做的是,在网页顶部添加以下属性作为链接(link)。

<link rel="dns-prefetch" href="//host_name_to_prefetch.com">

DNS预取是在用户尝试点击链接前试图解析域名。一旦域名被解析,且用户导航到该域名,则不会因DNS查找而导致加载时间变长。在这个博客主页里,有很多跳转到不同帖子的链接。如果能在用户导航到下一个页面前,预取一些外部链接的DNS,这将会大大减少下一个页面的DNS查找时间。根据Chromium
documentation所说,如果用户能将域名解析成IP地址并且缓存之,则DNS查找时间能低至0-1毫秒(千分之一秒)。这是相当令人印象深刻的!

我在网站添加DNS预取功能后,确实能显著改善页面加载时间。目前,这项技术被大多数主流浏览器所支持(除了IE),所以,当前没有任何理由不在你的web应用上使用这项技术!DNS预取是一个安全的HTML5特性,它会被那些不支持该技术的老旧浏览器简单忽略掉。如果你的网页内容是来自多个域名,那么这绝对是一个聪明的,能加快页面加载速度的方法。

打赏支持我翻译更多好文章,谢谢!

打赏译者

本文大部分内容翻译自雅虎前端的性能优化,如何让页面加载更快,雅虎给出了多个规则,原文地址:Best
Practices for Speeding Up Your Web Site
。主要从八个方向分别介绍了如何进行性能的优化。

这是一篇关于 <u>如何加快网站访问速度</u> 的译文,原文出自
雅虎开发者网站,原标题为
Best Practices for Speeding Up Your Web
Site。

本文是大名鼎鼎的雅虎前端优化规则(Yslow)的翻译。翻译并不逐字逐句,部分难以逐字翻译的被意译了,另外一些不重要的举例等也被精简。

在这篇长文章中,我将分享个人项目经验,一些关于快速简单且非常有趣的WEB性能知识的点点滴滴,以便使你的行为可以像一个初级的网页设计师和前端开发者;希望对任何想开始学习性能的人,有一定的启迪作用,并使你的前端项目变得超快。我相信这些技巧你能很快掌握,并轻松实现。因为都只需要一点小技巧,以及一些浏览器怎样工作的基础知识。

打赏支持我翻译更多好文章,谢谢!

任选一种支付方式

永利酒店赌场 3
永利酒店赌场 4

赞 1 收藏
评论

1.1 最小化HTTP请求

雅虎军规上说明80%的响应时间都来自前端,大多数页面的加载时间都是在下载图片,样式,js,flash等,减少组件的数量反过来减少请求的数量是页面加载更快的关键。

减少页面组件数量的一种方法是简化页面设计,但是如何在构建更丰富内容的基础上,同时还能减少相应时间?

  • Combined file
    ,合并文件,可以通过合并JavaScript,CSS文件来减少HTTP请求的数量来缩短响应时间。
  • CSS Sprites
    ,CSS精灵,是减少图片请求数量的首选方法,通过将背景图合并为单个图像,
    通过background-imagebackground-position
    属性来显示部分需要的图像。
  • Image maps
    ,图像地图,通过将多张图片合成为一张图片,整体大小大致相同,但减少HTTP请求的数量会加快页面的速度。
    一般用于如导航条 ,定义图像坐标容易出错,不推荐使用。
  • Inline images
    ,内联图像,使用data:url scheme将图像嵌入实际页面中。

以下为译文:

本文从内容,服务器,图片,css,js,cookie,和组件7个部分来谈网站优化。

注意
本文需要预先知晓一些基础的性能知识,如果有任何你不熟悉的就Google搜索一下好了!

关于作者:刘健超-J.c

永利酒店赌场 5

前端,在路上…
个人主页 ·
我的文章 ·
19 ·
    

永利酒店赌场 6

1.2 减少DNS查找

DNS就像电话簿将人们的姓名映射到他们的电话号码一样,当您输入www.yahoo.com时,浏览器会通过DNS解析返回服务器的IP地址,这个DNS解析过程需要成本,通常需要20-120ms才能解析成功,在这之前,浏览器无法从服务器获取任何内容。

通过缓存DNS查找来获得更好的性能。DNS信息保留在操作系统的DNS缓存中,大多数的浏览器都有自己的缓存,与操作系统的分开。

默认情况,IE会将DNS查找缓存30分钟,FireFox缓存一分钟。

当客户端的DNS缓存为空(对于浏览器和操作系统)时,DNS查找的数量等于网页中唯一主机名的数量。
减少唯一主机名的数量可减少DNS查找的数量。

减少唯一主机名的数量有可能减少页面中发生的并行下载量。避免DNS查找会缩短响应时间,但减少并行下载可能会缩短响应时间。
准则是将这些组件分成至少两个但不超过四个主机名。这是减少DNS查找和允许高度并行下载之间的良好折衷。


原文:Creeper
地址:https://github.com/creeperyang/blog/issues/1

基础知识

1.3 避免重定向

使用301和302状态码完成重定向。下面是一个301响应http头示例:

HTTP/1.1 301 Moved PermanentlyLocation: http://example.com/newuriContent-Type: text/html

浏览器自动将用户带到Location字段指定的URL。跳转所需的所有信息都在http头
,响应的主体通常是空的。301或302响应一般不会被缓存,除非有Expires
或者Cache-Control 指定要缓存。

要记住的主要事情是重定向会降低用户体验。在用户和HTML文档之间插入重定向会延迟页面中的所有内容,因为页面中的任何内容都无法呈现,并且在HTML文档到达之前不会开始下载任何组件。

最浪费的重定向之一经常发生,就是在URL中缺少尾部/
会产生301响应,比如http://astrology.yahoo.com/astrology301跳转到http://astrology.yahoo.com/astrology/

加速网站访问的最佳实践

卓越的绩效团队已经确定了一些使网页快速的最佳做法。该清单包括分为7个类别的35个最佳做法。


如何让web页面更快,雅虎团队实践总结了7类35条规则,下面一一列出。

关于性能,有一些知识在所有的设计师和前端开发者中广为传播。例如,尽可能少的请求,优化图片,把样式表(stylesheets)放在<head>,
把JS放在</body>之前, 最小化(minifying) JS 和 CSS
等等。这些基础知识已经被用来加快用户响应了,但还有更多更多需要学习。

1.4 使Ajax可缓存

使Ajax可缓存的好处之一就是在用户请求时可以提供快速反馈,因为它从后端Web服务器异步请求信息。重要的是要记住“异步”并不意味着“瞬时”。

为了提高性能,优化这些Ajax响应非常重要。提高Ajax性能的最重要方法是使响应可缓存,其中提高的方法除了Add
an Expires or a Cache-Control Header 中讨论的之外,其他方法还有:

  • gzip组件
  • 减少DNS查找
  • 压缩JS
  • 避免重定向
  • 设置ETags

Content

  1. 最小化 HTTP 请求
    最终用户响应时间的80%用于前端。大部分时间都是下载页面中的所有组件:图像,样式表,脚本,Flash等。减少组件数量又减少了呈现页面所需的HTTP请求数量。这是更快页面的关键。

减少页面中组件数量的一种方法是简化页面的设计。但是,有没有办法构建更丰富内容的页面,同时也能实现快速的响应时间?以下是减少HTTP请求数量的一些技术,同时仍然支持丰富的页面设计。

组合文件
是通过将所有脚本组合到单个脚本中以及将所有CSS组合到单个样式表中的方式来减少HTTP请求的数量。当脚本和样式表从页到页不同时,组合文件更具挑战性,但使这部分版本过程能够改善响应时间。

CSS
Sprites
是减少图像请求数量的首选方法。将您的背景图像合并为一个图像,并使用CSS
background-imagebackground-position 属性来显示所需的图像段。

图像映像将多个图像组合成单个图像。总体大小大致相同,但减少HTTP请求数量会加快页面速度。如果图像在页面中是连续的,则图像映射只能工作,例如导航栏。定义图像映射的坐标可能很繁琐,容易出错。

使用导航图像映射也不可访问,因此不推荐使用。
内联图像
使用data:URL方案将图像数据嵌入到实际页面中。这可以增加HTML文档的大小。将内联图像组合到(缓存)样式表中是减少HTTP请求并避免增加页面大小的一种方法。所有主流浏览器都不支持内联图片。

减少页面中HTTP请求的数量是开始的地方。这是提高首次访问者效能的最重要的指导方针。如Tenni
Theurer的博客文章中所述浏览器缓存使用 –
暴露!,您网站的每日访问者中有40-60%的空白缓存。

使您的页面快速为这些第一次访问者是更好的用户体验的关键。

  1. 减少DNS查询
    域名系统(DNS)将主机名映射到IP地址,就像电话簿将人员姓名映射到他们的电话号码一样。当您在浏览器中输入www.yahoo.com时,浏览器联系的DNS解析器会返回该服务器的IP地址。DNS有一个成本。DNS通常需要20-120毫秒来查找给定主机名的IP地址。在完成DNS查找之前,浏览器无法从此主机名下载任何内容。
    缓存DNS查找以获得更好的性能。这种缓存可以在由用户的ISP或局域网维护的特殊缓存服务器上发生,但是也存在在个人用户的计算机上发生的缓存。DNS信息保留在操作系统的DNS缓存(Microsoft
    Windows中的“DNS客户端服务”)中。大多数浏览器都有自己的缓存,与操作系统的缓存分开。只要浏览器将DNS记录保存在自己的缓存中,就不会对操作系统造成记录请求的麻烦。
    默认情况下,Internet Explorer会缓存DNS查找30分钟,由
    DnsCacheTimeout注册表设置指定。Firefox缓存DNS查找1分钟,由network.dnsCacheExpiration配置设置控制。(Fasterfox将其更改为1小时。)
    当客户端的DNS缓存为空(对于浏览器和操作系统)时,DNS查找的数量等于网页中唯一主机名的数量。这包括在页面的URL,图像,脚本文件,样式表,Flash对象等中使用的主机名。减少唯一主机名的数量减少了DNS查找的数量。
    减少唯一主机名的数量有可能减少页面中发生的并行下载量。避免DNS查找减少响应时间,但减少并行下载可能会增加响应时间。我的准则是将这些组件分成至少两个但不超过四个主机名。这导致减少DNS查找并允许高度并行下载之间的良好折中。

  2. 避免重定向
    使用301和302状态代码完成重定向。以下是301响应中HTTP头的示例:

HTTP/1.1 301 Moved Permanently
Location: http://example.com/newuri
Content-Type: text/html

浏览器自动将用户带到该Location字段中指定的URL。重定向所需的所有信息都在头文件中。响应的身体通常是空的。尽管他们的名字,在实践中也不会缓存301和302的响应,除非额外的标题,例如
Expires或者Cache-Control表明它应该是。元刷新标签和JavaScript是将用户引导到其他URL的其他方法,但如果必须执行重定向,首选技术是使用标准的3xx
HTTP状态代码,主要是为了确保后退按钮正常工作。

要记住的是重定向会减慢用户体验。在用户和HTML文档之间插入重定向会延迟页面中的所有内容,因为页面中的任何内容都不能被渲染,并且在HTML文档到达之前不会开始下载任何组件。

最浪费的重定向之一是频繁发生的,Web开发人员通常不会意识到这一点。当URL中缺少尾部斜线(/)时,会发生这种情况,否则应该有一个。
例如,去
http://astrology.yahoo.com/astrology
得到一个包含重定向到
http://astrology.yahoo.com/astrology/
(注意添加的尾部斜杠)的301响应。如果您使用Apache处理程序,则使用Aliasormod_rewriteor
DirectorySlash指令在Apache中进行修复。

将旧网站连接到新的网站是重定向的另一个常见用途。其他包括连接网站的不同部分,并根据某些条件(浏览器类型,用户帐户类型等)指导用户。使用重定向连接两个网站很简单,只需要很少的附加编码。尽管在这些情况下使用重定向会降低开发人员的复杂性,但会降低用户体验。这种使用重定向的替代方案包括使用Aliasmod_rewrite如果两个代码路径托管在同一台服务器上。如果域名变化是使用重定向的原因,一种替代方法是创建一个CNAME与组合(即建立了一个从域名指向另一个别名DNS记录)Aliasmod_rewrite

  1. 使用 Ajax Cacheable
    Ajax的一个引人注意的好处是它为用户提供即时反馈,因为它从后端Web服务器异步请求信息。但是,使用Ajax不能保证用户不会等待他们等待异步JavaScript和XML响应返回的大拇指。在许多应用中,用户是否保持等待取决于Ajax的使用方式。例如,在基于Web的电子邮件客户端中,用户将不断等待Ajax请求的结果来查找与其搜索条件匹配的所有电子邮件。重要的是要记住,“异步”并不意味着“瞬时”。

为了提高性能,重要的是优化这些Ajax响应。提高Ajax性能的最重要的方法是使响应可缓存,如添加到期或缓存控制头。
一些其他规则也适用于Ajax:

  • Gzip组件
  • 减少DNS查找
  • 缩小JavaScript
  • 避免重定向
  • 配置ETag

我们来看一个例子。
Web 2.0电子邮件客户端可能会使用Ajax下载用户的自动完成地址簿。
如果用户上次使用电子邮件网络应用程序后用户没有修改她的地址簿,如果Ajax响应可以使用未来的Expires或Cache-Control标头进行缓存,则可以从缓存读取以前的地址簿响应。必须通知浏览器何时使用先前缓存的地址簿响应,而不是请求新的地址簿响应。这可以通过向地址簿Ajax
URL添加一个时间戳来表示,例如,用户最后一次修改她的地址簿&t=1190241612。如果地址簿自上次下载以来没有被修改,则时间戳将是相同的,并且地址簿将从浏览器的缓存中读取,从而消除额外的HTTP往返。

即使您的Ajax响应是动态创建的,并且可能仅适用于单个用户,但仍可缓存它们。这样做会使您的Web
2.0应用程序更快。

  1. 后负载组件
    你可以仔细看看你的页面,问问自己:“为了最初渲染页面绝对需要什么?”
    其余的内容和组件可以等待。

JavaScript是在onload事件之前和之后拆分的理想候选者。
例如,如果您有JavaScript代码和库进行拖放和动画,那么可以等待,因为在初始呈现之后拖动页面上的元素。
其他寻找候选人进行后期加载的地方包括隐藏的内容(用户操作后出现的内容)以及下方的图像。

帮助您解决问题的工具:YUI Image
Loader允许您将图像延迟到折叠位置,YUI
Get实用程序是一个简单的方法,可以即时包括JS和CSS。举个例子,在野外看看
Yahoo!主页与Firebug的网络面板打开了。

当性能目标与其他Web开发最佳实践相一致时,这是很好的。
在这种情况下,渐进增强的想法告诉我们,当JavaScript被支持时,可以改善用户体验,但是您必须确保页面的工作即使没有JavaScript。
所以在确定页面工作正常之后,您可以使用一些后加载脚本来增强它,从而为您提供更多铃声和口哨,如拖放和动画。

  1. 预加载组件
    预加载可能看起来与后期加载相反,但实际上具有不同的目标。通过预加载组件,您可以利用浏览器空闲的时间,并请求将来需要的组件(如图像,样式和脚本)。这样当用户访问下一页时,您可以将大部分组件放在缓存中,并且您的页面将为用户加载更快。

实际上有几种类型的预加载:

  • 无条件预 加载 – 一旦加载启动,您就可以继续提取一些额外的组件。
    检查google.com,了解如何请求一个精灵图像的加载。
    这个精灵图片不需要在google.com主页上,但在连续的搜索结果页面上是需要的。
  • 有条件的预加载 –
    基于用户操作,您做出有根据的猜测,用户在哪里下一步,并相应地预加载。在search.yahoo.com上,您可以看到在输入框中输入后,如何请求一些额外的组件。
  • 预计预加载 – 在启动重新设计之前提前预加载。
    经常重新设计后,您会发现:“新网站很酷,但比以前更慢”。
    问题的一部分可能是用户正在使用完整缓存访问您的旧站点,但新的站点始终是空缓存体验。您可以在启动重新设计之前预先加载某些组件来减轻这种副作用。您的旧网站可以使用浏览器空闲的时间,并请求新网站将使用的图像和脚本
  1. 减少DOM元素的数量
    复杂的页面意味着更多的字节下载,也意味着JavaScript中的DOM访问速度较慢。如果您想要添加事件处理程序,例如,如果循环访问500或5000个页面上的DOM元素,这将有所作为。

大量的DOM元素可能是一些症状,应该使用页面的标记进行改进,而不必删除内容。您是否使用嵌套表进行布局?你是否<div>只投入更多的东西来解决布局问题?也许有更好的和更语义上正确的方式来做你的标记。

对于布局来说,很大的帮助是YUI
CSS实用程序:grids.css可以帮助您整体布局,fonts.css和reset.css可以帮助您剥离浏览器的默认格式。这是一个机会,开始新鲜和思考你的标记,例如,<div>只有当它有意义的语义,而不是因为它呈现一个新的行。

DOM元素的数量很容易测试,只需输入Firebug的控制台:

 document.getElementsByTagName('*').length

DOM元素有多少?检查其他具有良好标记的类似页面。例如,Yahoo!主页是一个非常繁忙的页面,仍然低于700个元素(HTML标签)。

  1. 分割跨域的组件
    分割组件允许您最大程度地并行下载。由于DNS查询损失,请确保您使用的不超过2-4个域。例如,您可以承载你的HTML和动态内容www.example.org之间分裂静电元件static1.example.org和static2.example.org

有关更多信息,请参阅Tenni Theurer和Patty
Chi的“最大化拼车车道中的并行下载
”。

  1. 最小化iframe的数量
    iframe允许在父文档中插入一个HTML文档。了解iframe的工作原理,以便有效的使用非常重要。
  • <iframe> 优点:
    帮助缓慢的第三方内容,如徽章和广告
    安全沙箱
    并行下载脚本

  • <iframe> 缺点:
    成本高,即使空白
    阻止页面加载
    非语义

  1. 没有404s
    HTTP请求是昂贵的,所以发出HTTP请求并获得无用的响应(即404 Not
    Found)是完全不必要的,并且会减慢用户体验,没有任何好处。

一些网站有帮助404s“你的意思是X?”,这对用户体验非常好,但也会浪费服务器资源(如数据库等)。特别糟糕的是当链接到外部JavaScript是错误的,结果是404.首先,这个下载将阻止并行下载。接下来,浏览器可能会尝试解析404响应体,就像它是JavaScript代码,试图找到可用的东西。


雅虎前端优化35条规则翻译

虽然在我们每天的工作生活中,浏览器给我们制造麻烦,使我们头疼,但请记住,他们也是很聪明的;
它们为我们做了很多性能优化工作,
所以大量的性能调优知识不但要知道浏览器在哪里给我们做了优化,还要知道怎么更好的挖掘它们。大量性能调优诀窍只是理解,利用和操纵浏览器已经替我们做好的优化工作。

1.5 延迟加载组件

你可以自习看看你的页面并问问你自己,最初页面的渲染需要什么,其他的内容和组件就是可以延迟加载的。

JavaScript是在 onload
时间之前和之后拆分的理想候选者,例如,如果您有拖放和动画的JS代码,则可以延迟加载,因为它需要在页面渲染完之后才可以执行。其它可延迟的包括隐藏的内容,折叠起来的图片等等。

Server

1. Content

顶部的Styles, 底部的scripts

1.6 预加载组件

预加载看起来和延迟加载相反,但它实际上有着不同的目标,通过预加载组件,您可以利用浏览器空闲的时间并请求将来需要的组件(如图像,样式和脚本)。这样,当用户访问下一页时,您可以将大部分组件放在缓存中,并且用户加载页面将更快。

有几种预加载类型:

  • 无条件预加载:一旦onload触发,你立即获取另外的组件。比如谷歌会在主页这样加载搜索结果页面用到的雪碧图。
  • 有条件预加载:基于用户操作,您可以进行有根据的猜测,即用户前进的位置并相应地预加载。
  • 预期的预加载:在旧网页预加载新网页的部分组件,那么切换到新网页时就不会是没有任何缓存了。

1.1 Make Fewer HTTP Requests

Minimize HTTP Requests减少/最小化 http 请求数。

到终端用户的响应时间80%花在前端:大部分用于下载组件(js/css/image/flash等等)。减少组件数就是减少渲染页面所需的http请求数。这是更快页面的关键。

减少组件数的一个方法就是简化页面设计。保持富内容的页面且能减少http请求,有以下几个技术:

  • Combined
    files。合并文件,如合并js,合并css都能减少请求数。如果页面间脚本和样式差异很大,合并会更具挑战性。
  • CSS Sprites。雪碧图可以合并多个背景图片,通过background-image
    background-position 来显示不同部分。
  • Image
    maps。合并多个图片到一个图片,一般用于如导航条。由于定义坐标的枯燥和易错,一般不推荐
  • Inline images。使用data:url scheme来內连图片。

减少请求数是为第一次访问页面的用户提高性能的最重要的指导。

这真的是一条基本规则,每个人都能非常容易的在大多数时间遵守,但为什么它重要?简短的说:

1.7 减少DOM数量

复杂页面意味着要下载更多字节,这也意味着JavaScript中的DOM访问速度更慢。例如,当您想要添加事件处理程序时,如果在页面上循环遍历500或5000个DOM元素,则会有所不同。

1.2 Reduce DNS Lookups

减少DNS查询。

就像电话簿,你在浏览器地址栏输入网址,通过DNS查询得到网站真实IP。

DNS查询被缓存来提高性能。这种缓存可能发生在特定的缓存服务器(ISP/local
area
network维护),或者用户的计算机。DNS信息留存在操作系统DNS缓存中(在windows中就是
DNS Client Serve
)。大多浏览器有自己的缓存,独立于操作系统缓存。只要浏览器在自己的缓存里有某条DNS记录,它就不会向操作系统发DNS解析请求。

IE默认缓存DNS记录30分钟,FireFox默认缓存1分钟。

当客户端的DNS缓存是空的,DNS查找次数等于页面中的唯一域名数。

减少DNS请求数可能会减少并行下载数。避免DNS查找减少响应时间,但减少并行下载数可能会增加响应时间。指导原则是组件可以分散在至少2个但不多于4个的不同域名。这是两者的妥协。

  • CSS 块渲染,
    因此你需要立即处理它(即在文档的顶部,在你的<head>之中)。
  • JS 块下载,
    因此你需要最后处理它们,以确保它们没有耽误页面中任何其它东西。

1.8 跨域拆分组件

拆分组件来达到最大化的并行下载,由于DNS查询的副作用,最好保证使用的域名不准超过2-4个。例如,您可以托管HTML和动态内容,www.example.org
并在static1.example.org和之间拆分静态组件。

1.3 Avoid Redirects

避免跳转。

跳转用301302状态码来达成。一个301响应http头的例子:

HTTP/1.1 301 Moved Permanently

Location: http://example.com/newuri

Content-Type: text/html

浏览器自动跳转到Location指定的路径。跳转所需的所有信息都在http头,所以http主体一般是空的。301
302响应一般不会被缓存,除非有额外的头部信息,比如ExpiresCache-Control指定要缓存。meta刷新标签或
JavaScript
也可以跳转,但如果真要跳转,3xx跳转更好,主要是保证返回键可用。

跳转显然拖慢响应速度。在跳转的页面被获取前浏览器没什么能渲染,没什么组件能下载。

最浪费的跳转之一发生在url尾部slash(/)缺失。比如http://astrology.yahoo.com/astrology301跳转到http://astrology.yahoo.com/astrology/。这可以被Apache等服务器修复,用Aliasmod_rewrite等等。

CSS块渲染是因为浏览器总是试图渐进式的渲染页面;它们想在元素到达的时候顺序的渲染它。如果style在距离很远的页面下部,浏览器在获得它之前没有办法渲染那个CSS。因为这个原因,如果浏览器在渲染文档过程中,改变了之前渲染的东西,它们可以避免style的重绘。浏览器在它获得所有需要的style信息之前不会渲染页面,如果你将style放在文档底部,你就是在使浏览器等待,阻塞了渲染。

1.9 最少的iframe

iframe允许html文档被插入到父文档。

<iframe>优点:

  • 帮助解决缓慢的第三方内容的加载,如广告和徽章
  • 安全沙盒
  • 并行下载脚本

<iframe>缺点:

  • 即使空的也消耗
  • 阻塞了页面的onload
  • 非语义化

1.4 Make Ajax Cacheable

让Ajax可缓存。

使用ajax的好处是可以向用户提供很快的反馈,因为它是向后台异步请求数据。但是,这些异步请求不保证用户等待的时间——异步不意味着瞬时。

提高ajax性能的最重要的方法是让响应被缓存,即在Add an Expires or a
Cache-Control
Header中讨论的
Expires 。其它方法是:

  • gzip组件
  • 减少DNS查找
  • 压缩JS
  • 避免跳转
  • 设置ETags

所以,只要你将CSS放在页面的顶部,那么浏览器就可以立刻开始渲染。

1.10 不要出现404

HTTP的请求是非常昂贵的,因此发出的HTTP请求获得无用的响应是完全没有必要的,并且会影响用户体验。

一些网站会有特别的404页面提高用户体验,但这仍然会浪费服务器资源。特别坏的是当链接指向外部js但却得到404结果。这样首先会降低并行下载数,其次浏览器可能会把404响应体当作js来解析,试图从里面找出可用的东西。

1.5 Post-load Components

延迟加载组件。

再看看你的页面然后问问自己,“什么是页面初始化必须的?”。剩下的内容和组件可以延迟。

JavaScript是理想的(延迟)候选者,可以切分到onload事件之前和之后。比如拖放的js库可以延迟,因为拖动必须在页面初始化之后。其它可延迟的包括隐藏的内容,折叠起来的图片等等。

JavaScript块下载是由于好几个原因(这又是浏览器聪明之处),但首先我们需要知道浏览器里的资源下载是如何实际发生的;简单的说,浏览器会从一个单一的域名并行的尽可能多的下载资源。它从越多的域名下载,就能在一瞬间并行的获得更多的资源。

2.1 使用CDN

用户与Web服务器的距离会对响应时间产生影响。在多个地理位置分散的服务器上部署内容将使您的页面从用户的角度加载更快。

CDN是一群不同地点的服务器,可以更高效地分发内容到用户。

1.6 Preload Components

预加载组件。

预加载看起来与延迟加载相反,但它的确有个不同的目标。通过预加载你可以利用浏览器的空闲时间来请求你将来会用到的组件。这样当用户访问下一个页面时,你会有更多的组件已经在缓存中,这样会极大加快页面加载。

有几种预加载类型:

  • 无条件预加载:一旦onload触发,你立即获取另外的组件。比如谷歌会在主页这样加载搜索结果页面用到的雪碧图。
  • 有条件预加载:基于用户动作,你推测用户下一步会去哪里并加载相应组件。
  • 预期的预加载:在发布重新设计(的网站)前提前加载。在旧网页预加载新网页的部分组件,那么切换到新网页时就不会是没有任何缓存了

JavaScript中断了这个过程,阻塞了从任何一个域名的并行的下载,因为:

2.2 添加Expries 或者 Cache-Control

这条规则有两个方面:

  • 对于静态组件:通过设置Expires头实现“永不过期”策略
  • 对于动态组件:使用适当的Cache-Control标头来帮助浏览器处理条件请求

页面内容越来越丰富,意味着页面中有更多脚本,样式表,图像以及Flash。您的页面的首次访问可能必须发出多个HTTP请求,但通过使用Expires标头,您可以使这些组件可缓存。

浏览器使用缓存来减少HTTP请求的数量和大小,从而加快网页加载速度。Web服务器使用HTTP响应中的Expires头来告诉客户端可以缓存组件多长时间。
比如:

Expires: Thu, 15 Apr 2010 20:00:00 GMT

表示在2010-04-15都可以请求缓存内容。

1.7 Reduce the Number of DOM Elements

减少dom数。

一个复杂的页面意味着更多的内容要下载,以及更慢的dom访问。比如在有500dom数量的页面添加事件处理就和有5000dom数量的不同。

如果你的页面dom元素很多,那么意味着你可能需要删除无用的内容和标签来优化。

  • 被调用的脚本可能改变页面,即浏览器在继续别的事情以前,将不得不处理它。因此为了处理那个不测事件,浏览器停止了任何其它东西的下载,以便集中精力关注于它。
  • 脚本正常工作经常需要依照一定的顺序加载,例如,要在加载一个插件之前加载jQuery。浏览器阻止了JavaScript的并行下载,因此它不会同时下载jQuery和你的插件;很显然如果你同时并行下载二者,你的插件会在jQuery之前到达。

2.3 Gzip组件

通过前端工程师做出的决策,可以显著减少在网络上传输HTTP请求和响应所需的时间。从HTTP
/ 1.1开始,Web客户端表示支持使用HTTP请求中使用Accept-Encoding进行压缩。

 Accept-Encoding:gzip,deflate

如果服务器看到这个头部,它可能会选用列表中的某个方法压缩响应。服务器通过Content-Encoding头部提示客户端:

Content-Encoding: gzip

gzip一般可减小响应的70%。尽可能去gzip更多类型的文件。html,脚本,样式,xml和json等等都应该被gzip,而图片,pdf等等不应该被gzip,因为它们本身已被压缩过,gzip压缩它们只是浪费cpu,甚至增加文件大小。

尽可能多地压缩文件类型是减轻页面重量和加速用户体验的简便方法。

1.8 Split Components Across Domains

把组件分散到不同的域名。

把组件分散到不同的域名允许你最大化并行下载数。由于DNS查询的副作用,最佳的不同域名数是2-4。

所以,由于浏览器在获取JavaScript的时候停止了所有其他下载,将你的JavaScript脚本放在文档中尽可能晚加载的地方是一个好主意。我相信你们都看到过页面中的空白片段,在那里第三方的JS脚本被花时间加载,并且它还阻止了页面其他资源的获取和渲染;这就是JavaScript的阻塞在作用了。

2.4 配置ETag

实体标记是Web服务器和浏览器用于确定浏览器缓存中的组件是否与源服务器上的组件匹配的机制。
添加ETag以提供验证比上次修改日期更灵活的实体的机制。ETag是唯一标识组件的特定版本的字符串。
服务器这样设置组件的ETag:

HTTP/1.1 200 OKLast-Modified: Tue, 12 Dec 2006 03:03:59 GMTETag: "10c24bc-4ab-457e1c1f"Content-Length: 12195

之后,如果浏览器要验证组件,它用If-None-Match头部来传ETag给服务器。如果ETag匹配,服务器返回304:

GET /i/yahoo.gif HTTP/1.1Host: us.yimg.comIf-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMTIf-None-Match: "10c24bc-4ab-457e1c1f"HTTP/1.1 304 Not Modified

1.9 Minimize the Number of iframes

最小化iframe的数量。

iframe允许html文档被插入到父文档。

<iframe>优点:

  • 帮助解决缓慢的第三方内容的加载,如广告和徽章
  • 安全沙盒
  • 并行下载脚本

<iframe>缺点:

  • 即使空的也消耗(资源和时间)
  • 阻塞了页面的onload
  • 非语义化(标签)

但是显然,现代浏览器还是变得聪明了。我将给你一个Andy
Davies寄给我的电子邮件的摘录,因为他解释的比我清楚:

2.5 尽早刷新Buffer

当用户请求页面时,后端服务器可能需要200到500毫秒才能将HTML页面拼接在一起。在此期间,浏览器在等待数据到达时处于空闲状态。
在PHP中,有函数flush()。它允许您将部分准备好的HTML响应发送到浏览器,以便浏览器可以在后端忙于HTML页面的其余部分时开始获取组件。这种好处主要出现在繁忙的后端或轻量级前端。

一个比较好的flush的位置是在head之后,因为浏览器可以加载其中的样式和脚本文件,而后台继续生成页面剩余部分。

<!-- css, js --></head><?php flush(); ?><body><!-- content -->

1.10 No 404s

不要404。

http请求是昂贵的,所以发出http请求但获得没用的响应(如404)是完全不必要的,并且会降低用户体验。

一些网站会有特别的404页面提高用户体验,但这仍然会浪费服务器资源。特别坏的是当链接指向外部js但却得到404结果。这样首先会降低(占用)并行下载数,其次浏览器可能会把404响应体当作js来解析,试图从里面找出可用的东西。

现代浏览器将并行下载JS,只有在脚本被执行的时候阻塞渲染(显然脚本必须也被下载了)。脚本下载常常被浏览器的预加载器所完成。当浏览器页面渲染被阻塞,即等待CSS,或JS被执行,预分析器将扫描页面剩余部分,寻找它能下载的资源。有些浏览器如
Chrome,
将分先后下载资源,例如,如果脚本与图片同时在等待下载,它将先下载脚本。

2.6 AJAX 使用 GET 请求

在雅虎邮件团队发现,在使用时XMLHttpRequest,POST在浏览器中实现为两步过程:首先发送头部,然后发送数据。因此最好使用GET,它只需要一个TCP数据包发送(除非你有很多cookie)。IE中的最大URL长度为2K,因此如果发送的数据超过2K,则可能无法使用GET。

POST不提交任何数据跟GET行为类似,但从语义上讲,获取数据应该用GET,提交数据到服务器用POST。

2. Server

漂亮的内容!

2.7 避免空src的图片

空src属性的图片的行为可能跟你预期的不一样。它有两种形式:

  1. html标签:<img src="">
  2. js:var img = new Image(); img.src = "";

两种形式都会产生相同的效果:浏览器向您的服务器发出另一个请求

  • Internet Explorer向页面所在的目录发出请求。
  • Safari和Chrome会向实际页面提出请求。
  • Firefox
    3及更早版本的行为与Safari和Chrome相同,但3.5版解决了此问题[错误444931],不再发送请求。
  • 遇到空图像时,Opera不执行任何操作。
  1. 由于发送大量的意料之外的流量,会削弱服务器,尤其那些每天pv上百万的页面。
  2. 浪费服务器计算周期取生成不会被浏览的页面。
  3. 可能会破坏用户数据。如果你在跟踪请求状态,通过cookie或其它,你可能会破坏数据。即使image的请求不会返回图片,但所有的头部数据都被浏览器读取了,包括cookie。即使剩下的响应体被丢弃,破坏可能已经发生。

2.1 Use a Content Delivery Network

使用CDN。

永利酒店赌场 ,用户接近你的服务器会减少响应时间。把你的内容发布到多个,地理上分散的服务器可以让页面加载更快。但怎么开始?

首先不要试图把你的架构重新设计成分布式架构。因为可能引进更多复杂性和不可控。

记住80-90%的终端用户响应时间花费在下载页面中的所有组件:图片、样式、脚本、falsh等等。这是Performance
Golden
Rule
。不要从困难的重新设计后台架构开始,最好首先分发你的静态内容。这不仅可以减少响应时间,用CDN还很容易来做。

CDN是一群不同地点的服务器,可以更高效地分发内容到用户。一些大公司有自己的CDN。

所以,要使页面被尽可能快的渲染,将styles放在顶部。为了阻止JS的阻塞影响到渲染,将scripts放在底部。

3.1 减小Cookie大小

http
cookie的使用有多种原因,比如授权和个性化。cookie的信息通过http头部在浏览器和服务器端交换。尽可能减小cookie的大小来降低响应时间。

  • 消除不必要的cookie。
  • 尽可能减小cookie的大小来降低响应时间。
  • 注意设置cookie到合适的域名级别,则其它子域名不会被影响。
  • 正确设置Expires日期。早一点的Expires日期或者没有会尽早删除cookie,优化响应时间。

2.2 Add an Expires or a Cache-Control Header

Expires或者Cache-Control头部。

这条规则有两个方面:

  • 对静态组件:通过设置Expires头部来实现“永不过期”策略。
  • 对动态组件:用合适的Cache-Control头部来帮助浏览器进行有条件请求。

页面越来越丰富,意味着更多脚本,样式,图片等等。第一次访问的用户可能需要发出多个请求,但使用Expires可以让这些组件被缓存。这避免了访问子页面时没必要的http请求。Expires一般用在图片上,但应该用在所有的组件上。

浏览器(以及代理)使用缓存来减少http请求数,加快页面加载。服务器使用http响应的Expires头部来告诉客户端一个组件可以缓存多久。比如下面:

Expires: Thu, 15 Apr 2010 20:00:00 GMT //2010-04-15

注意,如果你设置了Expires头部,当组件更新后,你必须更改文件名。

更少的请求

3.2 用没有cookie的域名提供组件。

当浏览器发出静态图像请求并将cookie与请求一起发送时,服务器对这些cookie没有任何用处。所以他们只是没有充分理由创建网络流量。您应该确保使用无cookie请求请求静态组件。创建一个子域并在那里托管所有静态组件。

如果您的域名是www.example.org,您可以托管您的静态组件static.example.org。但是,如果您已经在顶级域上设置了cookie
example.org而不是www.example.org,则所有请求都
static.example.org将包含这些cookie。在这种情况下,您可以购买一个全新的域,在那里托管您的静态组件,并保持此域无cookie

2.3 Gzip Components

传输时用gzip等压缩组件。

http请求或响应的传输时间可以被前端工程师显著减少。终端用户的带宽,ISP,接近对等交换点等等没法被开发团队控制,但是,压缩可以通过减少http响应的大小减少响应时间。

HTTP/1.1开始,客户端通过http请求中的Accept-Encoding头部来提示支持的压缩:

Accept-Encoding: gzip, deflate

如果服务器看到这个头部,它可能会选用列表中的某个方法压缩响应。服务器通过Content-Encoding头部提示客户端:

Content-Encoding: gzip

gzip一般可减小响应的70%。尽可能去gzip更多(文本)类型的文件。html,脚本,样式,xml和json等等都应该被gzip,而图片,pdf等等不应该被gzip,因为它们本身已被压缩过,gzip它们只是浪费cpu,甚至增加文件大小。

另一个明显而基本的性能优化方法是少下载。页面需要的每一个资源就是一次额外的HTTP请求;浏览器不得不停下来去获取每一个用于渲染页面所需的资源。每一次HTTP请求都可能引发DNS查询,重定向,404,等等。每一次HTTP请求,无论为了样式表,图片,web字体,JS文件还是其它你能想到的,都可能是一次非常昂贵的操作。尽量减少这些请求是你可以做的最快的优化方法中的一种.

4.1 将CSS放在顶部

在研究Yahoo!的性能时,我们发现将样式表移动到文档HEAD会使页面看起来加载速度更快。这是因为将样式表放在HEAD中允许页面逐步呈现。

关注性能的前端工程师希望页面被逐步渲染,这时因为,我们希望浏览器尽早渲染获取到的任何内容。这对大页面和网速慢的用户很重要。给用户视觉反馈,比如进度条的重要性已经被大量研究和记录。在我们的情况中,HTML页面就是进度条。当浏览器逐步加载页面头部,导航条,logo等等,这些都是给等待页面的用户的视觉反馈。这优化了整体用户体验。

把样式表放在文档底部的问题是它阻止了许多浏览器的逐步渲染,包括IE。这些浏览器阻止渲染来避免在样式更改时需要重绘页面元素。所以用户会卡在白屏。

2.4 Configure ETags

实体标记(Entity
tags,ETag)是服务器和浏览器之间判断浏览器缓存中某个组件是否匹配服务器端原组件的一种机制。实体就是组件:图片,脚本,样式等等。ETag被当作验证实体的比最后更改(last-modified)日期更高效的机制。服务器这样设置组件的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给服务器。如果ETag匹配,服务器返回304:

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

ETag的问题是它们被构造来使它们对特定的运行这个网站的服务器唯一。浏览器从一个服务器获取组件,之后向另一个服务器验证,ETag将不匹配。然而服务器集群是处理请求的通用解决方案。

如果不能解决多服务器间的ETag匹配问题,那么删除ETag可能更好。

再谈到浏览器和并行;大多数浏览器一次只从每个引用的域下载一些资源,而JS会阻塞这些下载。所以,你做的每一个HTTP请求都应该仔细考虑,而不是随便随便做的。

4.2 避免CSS表达式

CSS表达式是强大的设置动态CSS属性的方法。IE5开始支持,IE8开始不赞成使用。例如,背景颜色可以设置成每小时轮换:

background-color: expression( (new Date.getHours()%2 ? "#B8D4FF" : "#F08A00" );

表达式的问题在于它们的评估频率高于大多数人的预期。它们不仅在页面呈现和调整大小时进行重新计算,而且在页面滚动时甚至在用户将鼠标移动到页面上时进行计算。在CSS表达式中添加计数器可以让我们跟踪CSS表达式的计算时间和频率。在页面上移动鼠标可以轻松计算超过10,000次。

2.5 Flush the Buffer Early

早一点刷新buffer(尽早给浏览器数据)。

当用户请求一个页面,服务器一般要花200-500ms来拼凑整个页面。这段时间,浏览器是空闲的(等数据返回)。在php,有个方法flush()允许你传输部分准备好的html响应给浏览器。这样的话浏览器就可以开始下载组件,而同时后台可以继续生成页面剩下的部分。这种好处更多是在忙碌的后台或轻前端网站可以看到。

一个比较好的flush的位置是在head之后,因为浏览器可以加载其中的样式和脚本文件,而后台继续生成页面剩余部分。

<pre style=”background:#F6F8FA;box-sizing: border-box;word-wrap:
normal;
border-radius: 3px;overflow:auto”></pre>

<pre style=”background:#F6F8FA”></head></pre>

<pre style=”background:#F6F8FA”><?php flush();
?></pre>

<pre style=”background:#F6F8FA”><body></pre>

<pre style=”background:#F6F8FA”></pre>

尽可能并行

4.3 选择<link>而不是@import

之前的一个最佳原则是说CSS应该在顶部来允许逐步渲染。

在IE用@import和把CSS放到页面底部行为一致,所以最好别用。

2.6 Use GET for AJAX Requests

ajax请求用get。

Yahoo!
Mail团队发现当使用XMLHttpRequest,POST
被浏览器实现为两步:首先发送头部,然后发送数据。所以使用GET最好,仅用一个TCP包发送(除非cookie太多)。IE的url长度限制是2K。

POST但不提交任何数据根GET行为类似,但从语义上讲,获取数据应该用GET,提交数据到服务器用POST。

为了让浏览器能并行的下载更多资源,你可以由不同的域名提供服务。如果说,浏览器只能一次从一个域名获取两个资源,那么由两个域名提供服务意味着它可以一次性获取四个资源;三个域名意味着六个并行下载。

4.4 避免过滤器

专有的AlphaImageLoader过滤器旨在解决IE版本<7中的半透明真彩色PNG的问题。该过滤器的问题在于它在下载图像时阻止渲染并冻结浏览器。它还会增加内存消耗,并且每个元素应用,而不是每个图像,因此问题成倍增加。

最佳做法是放弃AlphaImageLoader,改用PNG8来优雅降级。

2.7 Avoid Empty Image src

避免空src的图片。

空src属性的图片的行为可能跟你预期的不一样。它有两种形式:

  1. html标签:<img src="">
  2. js:var img = new Image(); img.src = "";

两种都会造成同一种后果:浏览器会向你的服务器发请求。

  • IE,向页面所在的目录发请求。
  • Safari和Chrome,请求实际的页面。
  • FireFox3及之前和Safari/Chrome一样,但从3.5开始修复问题,不再发请求。
  • Opera遇到空图片src不做任何事。

为什么这种行为很糟糕?

  1. 由于发送大量的意料之外的流量,会削弱服务器,尤其那些每天pv上百万的页面。
  2. 浪费服务器计算周期取生成不会被浏览的页面。
  3. 可能会破坏用户数据。如果你在跟踪请求状态,通过cookie或其它,你可能会破坏数据。即使image的请求不会返回图片,但所有的头部数据都被浏览器读取了,包括cookie。即使剩下的响应体被丢弃,破坏可能已经发生。

这种行为的根源是uri解析发生在浏览器。RFC 3986
定义了这种行为,空字符串被当作相对路径,Firefox, Safari, 和
Chrome都正确解析,而IE错误。总之,浏览器解析空字符串为相对路径的行为被认为是符合预期的。

html5在4.8.2添加了对标签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.

幸运的是将来浏览器不会有这个问题了(在图片上)。不幸的是,<script src=""><link href="">没有这样的规范。

许多网站有静态/资源 域名;你可以发现, Twitter, 用 si0.twimg.com
来做静态资源:

5.1 将Script放在底部

脚本引起的问题是它们阻塞了并行下载。
HTTP1.1规范建议浏览器每个域名下不要一次下载超过2个组件。如果你的图片分散在不同服务器,那么你能并行下载多个图片。但当脚本在下载,浏览器不会再下载其它组件,即使在不同域名下。

有些情况下把脚本移动到底部并不简单。比如,脚本中用了document.write来插入内容,它就不能被移动到底部。另外有可能有作用域问题。但大多数情况,有方法可以解决这些问题。

一个替代建议是使用异步脚本。defer属性表明脚本不包含document.write,是提示浏览器继续渲染的线索。

3 Cookie

1 <link rel="stylesheet" href="https://si0.twimg.com/a/1358386289/t1/css/t1_core.bundle.css" type="text/css" media="screen">

5.2 使用外部JavaScript 和 CSS

在实际中使用外部文件通常会产生更快的页面,因为浏览器会缓存JavaScript和CSS文件。每次请求HTML文档时,都会下载HTML文档中内联的JavaScript和CSS。这减少了所需的HTTP请求数,但增加了HTML文档的大小。另一方面,如果JavaScript和CSS位于浏览器缓存的外部文件中,则HTML文档的大小会减少,而不会增加HTTP请求的数量。

3.1 Reduce Cookie Size

http
cookie的使用有多种原因,比如授权和个性化。cookie的信息通过http头部在浏览器和服务器端交换。尽可能减小cookie的大小来降低响应时间。

  • 消除不必要的cookie。
  • 尽可能减小cookie的大小来降低响应时间。
  • 注意设置cookie到合适的域名级别,则其它子域名不会被影响。
  • 正确设置Expires日期。早一点的Expires日期或者没有会尽早删除cookie,优化响应时间。

Facebook 用fbstatic-a.akamaihd.net:

5.3 压缩JavaScript 和 CSS

压缩就是删除代码中不必要的字符来减小文件大小,从而提高加载速度。当代码压缩时,注释删除,不需要的空格(空白,换行,tab)也被删除。

3.2 Use Cookie-free Domains for Components

用没有cookie的域名提供组件。

当浏览器请求静态图片并把cookie一起发送到服务器时,cookie此时对服务器没什么用处。所以这些cookie只是增加了网络流量。所以你应该保证静态组件的请求是没有cookie的。可以创建一个子域名来托管所有静态组件。

比如,你域名是www.example.org,可以把静态组件托管在static.example.org。不过,你如果把cookie设置在顶级域名example.org下,这些cookie仍然会被传给static.example.org。这种情况下,启用一个全新的域名来托管静态组件。

另外一个用没有cookie的域名提供组件的好处是,某些代理可能会阻止缓存待cookie的静态组件请求。

1 <link rel="stylesheet" href="https://fbstatic-a.akamaihd.net/rsrc.php/v2/yi/r/76f893pcD3j.css">

5.4 删除重复的脚本

在一个页面中两次包含相同的JavaScript文件会损害性能。这并不像你想象的那么不寻常。对美国十大顶级网站的评论显示,其中两个网站包含重复的脚本。两个主要因素会增加脚本在单个网页中重复的几率:团队规模和脚本数量。当它发生时,重复的脚本会通过创建不必要的HTTP请求和浪费的JavaScript执行来损害性能。

发出不必要的http请求发生在IE而不是Firefox。在IE,如果外部脚本引入两次且没有缓存,它会发出2个请求。即使脚本被缓存,刷新时也会发出额外请求。

除了增加http请求,时间被浪费在执行脚本多次上。不管IE还是Firefox都会执行多次。

4. CSS

通过这些静态的资源域名,
Twitter与Facebook能提供更多的并行资源服务;来自twitter.com和si0.twimg.com的资源可以协作方式下载。这真的是使你的页面上获得更多并发下载的简单方法,如果再加上实际的CDN技术就会更好,CDN技术通过从一个更加合适的物理位置提供资源服务的方法来减少延迟。

5.5 最小化DOM访问

使用JavaScript访问DOM元素的速度很慢,因此为了获得响应更快的页面,您应该:

  • 缓存访问过的元素的引用
  • 在DOM树外更新节点,然后添加到DOM树
  • 避免用JS实现固定布局

4.1 Put Stylesheets at the Top

把样式放在顶部。

研究雅虎网页性能时发现把样式表移到<head>里会让页面更快。这是因为把样式表移到<head>里允许页面逐步渲染。

关注性能的前端工程师希望页面被逐步渲染,这时因为,我们希望浏览器尽早渲染获取到的任何内容。这对大页面和网速慢的用户很重要。给用户视觉反馈,比如进度条的重要性已经被大量研究和记录。在我们的情况中,HTML页面就是进度条。当浏览器逐步加载页面头部,导航条,logo等等,这些都是给等待页面的用户的视觉反馈。这优化了整体用户体验。

把样式表放在文档底部的问题是它阻止了许多浏览器的逐步渲染,包括IE。这些浏览器阻止渲染来避免在样式更改时需要重绘页面元素。所以用户会卡在白屏。

HTML规范清楚表明样式应该在<head>里。

这全部都很好,但后面我们将讨论在特定环境下,怎样从子域名提供服务却会实际上对性能有害。

5.6 使用事件代理

有时候页面看起来不那么响应,是因为绑定到不同元素的大量事件处理函数执行太多次。这是为什么使用事件委托是一种好方法。

另外,你不必等到onload事件来开始处理DOM树,DOMContentLoaded更快。大多时候你需要的只是想访问的元素已在DOM树中,所以你不必等到所有图片被下载。

4.2 Avoid CSS Expressions

避免CSS表达式。

CSS表达式是强大的(可能也是危险的)设置动态CSS属性的方法。IE5开始支持,IE8开始不赞成使用。例如,背景颜色可以设置成每小时轮换:

<pre style=”background:#F6F8FA;box-sizing: border-box;word-wrap:
normal;
border-radius: 3px;overflow:auto”>background-color: expression( (new
Date()).getHours()%2 ? “#B8D4FF” : “#F08A00” );</pre>

CSS表达式的问题是它们可能比大多数人预期的计算的更频繁。它们不仅在页面载入和调整大小时重新计算,也在滚动页面甚至是用户在页面上移动鼠标时计算。比如在页面上移动鼠标可能轻易计算超过10000次。

要避免CSS表达式计算太多次,可以在它第一次计算后替换成确切值,或者用事件处理函数而不是CSS表达式

因此,现在有了我们关于性能的基础知识:

6.1 优化图片

  • 检查GIF并查看它们是否使用与图像中颜色数对应的调色板大小。
  • 可以把gif转成png看看有没有变小。除了动画,gif一般可以转成png8
  • 运行pngcrush或其它工具压缩png。
  • 运行jpegtran或其它工具压缩jpeg。

4.3 Choose <link> over @import

选择<link>而不是@import

之前的一个最佳原则是说CSS应该在顶部来允许逐步渲染。

在IE用@import和把CSS放到页面底部行为一致,所以最好别用

  • 将样式表放在文档的顶部
  • 将JavaScript放在底部(可能的地方)
  • 尽可能减少HTTP请求
  • 从多个域名提供资源服务能增加浏览器并行下载的资源数量。

6.2 优化CSS精灵图

  • 将图像水平排列在精灵图中而不是垂直排列通常会导致文件较小。
  • 把颜色近似的图片合并到一张精灵图,这样可以让颜色数更少,如果低于256就可以用png8.
  • “适应移动设备”并且不要在精灵中留下大的间隙。这不会影响文件大小,但需要较少的内存,以便用户代理将图像解压缩为像素图。

4.4 Avoid Filters

避免使用(IE)过滤器。

IE专有的AlphaImageLoader过滤器用于修复IE7以下版本的半透明真彩色PNG的问题。这个过滤器的问题是它阻止了渲染,并在图片下载时冻结了浏览器。另外它还引起内存消耗,并且它被应用到每个元素而不是每个图片,所以问题(的严重性)翻倍了。

最佳做法是放弃AlphaImageLoader,改用PNG8来优雅降级。

HTTP 请求与 DNS 查询

6.3 不要在HTML中缩放图片

不要使用比您需要的更大的图像,因为您可以在HTML中设置宽度和高度。如果您需要,
<img width="100" height="100" src="mycat.jpg" alt="My Cat" />
那么您的图像(mycat.jpg)应该是100x100px而不是缩小的500x500px图像。

5. JavaScript

每当你从任何域名请求一个资源,会发出一个带有相关头部,被访问资源的
HTTP请求,并且会返回一个响应。这是对该过程的一个极端简化,但它基本就是事实上你需要知道的。这是一个HTTP请求,而且所有涉及的资源都从属于这个往返的旅行。当提到前端性能,这些请求正是主要的瓶颈所在,因为如我们谈到的,浏览器受限于有多少请求可以并行发生。这也是为什么我们经常要使用子域名;以便允许这些请求在数个域名上发生,允许同时发生多得多数量的请求。

6.4 让 favicon.ico 小且可缓存

favicon.ico是在你服务器根路径的图片。邪恶的是即使你不关心它,浏览器仍然会请求它。所以最好不要响应404。另外由于在同一服务器,每次请求favicon.ico时也会带上cookie。这个图片还会影响下载顺序,比如在IE,如果你在onload时下载额外的组件,fcvicon会在这些组件之前被下载。

怎么减轻favicon.ico的缺点?

  • 小,最好1K以下
  • 设置Expires头部。也许可以安全地设置为几个月。

5.1 Put Scripts at the Bottom

把脚本放到底部。

脚本引起的问题是它们阻塞了并行下载。HTTP1.1规范建议浏览器每个域名下不要一次下载超过2个组件。如果你的图片分散在不同服务器,那么你能并行下载多个图片。但当脚本在下载,浏览器不会再下载其它组件,即使在不同域名下

有些情况下把脚本移动到底部并不简单。比如,脚本中用了document.write来插入内容,它就不能被移动到底部。另外有可能有作用域问题。但大多数情况,有方法可以解决这些问题。

一个替代建议是使用异步脚本。defer属性表明脚本不包含document.write,是提示浏览器继续渲染的线索。不幸的是,Firefox不支持。如果脚本能异步,那么也就可以移动到底部。

然而关于这还有个问题,DNS查询。每次(从一个空缓存)一个新的域名被引用,HTTP请求会受制于一个耗时的DNS查询(某个介于20到120毫秒之间的值),在DNS查询中,发出的请求会查询资源实际存在的地点;互联网通过IP地址被绑定在一起,这些地址由DNS管理的主机名引用。

7.1 保持组件小于25K

此限制与iPhone不会缓存大于25K的组件这一事实有关。请注意,这是未压缩的大小。在这里减少组件大小很重要,因为单独使用gzip可能还不够。

5.2 Make JavaScript and CSS External

使用外部JS和CSS。

这里的很多性能规则涉及外部组件怎么管理。但你首先要明白一个基本问题:JS和CSS是应该包含在外部文件还是內连在页面本身?

真实世界中使用外部文件一般会加快页面,因为JS和CSS文件被浏览器缓存了。內连的JS和CSS怎在每次HTML文档下载时都被下载。內连减少了http请求,但增加了HTML文档大小。另一方面,如果JS和CSS被缓存了,那么HTML文档可以减小大小而不增加HTTP请求。

核心因素,就是JS和CSS被缓存相对于HTML文档被请求的频率。尽管这个因素很难被量化,但可以用不同的指标来计算。如果网站用户每个session有多个pv,许多页面重用相同的JS和CSS,那么有很大可能用外部JS和CSS更好。

许多网站用这些指标计算后在中间位置。对这些网站来说,最佳方案还是用外部JS和CSS文件。唯一例外是內连更被主页偏爱,如http://www.yahoo.com/。主页每个session可能只有少量的甚至一个pv,这时候內连可能更快。

对多个页面的首页来说,可以通过技术减少(其它页面的)http请求。在首页用內连,初始化后动态加载外部文件,接下来的页面如果用到这些文件,就可以使用缓存了。

如果每个引用的新域名具有DNS查询的前端代价,你必须确保这个代价确实是值得的。如果是一个小网站(例如像CSS魔法),那么由子域名提供资源可能并不值得;相比执行多个域名的DNS查询并将其并行化来说,从一个域名非并行的获取若干资源,浏览器可能更快。

7.2 将组件打包到多部分文档中

将组件打包到多部分文档就像带有附件的电子邮件,它可以帮助您通过一个HTTP请求获取多个组件(请记住:HTTP请求很昂贵)。使用此技术时,首先检查用户代理是否支持它(iPhone不支持)。

原文地址:

5.3 Minify JavaScript and CSS

压缩JS和CSS。

压缩就是删除代码中不必要的字符来减小文件大小,从而提高加载速度。当代码压缩时,注释删除,不需要的空格(空白,换行,tab)也被删除。

混淆是对代码可选的优化。它比压缩更复杂,并且可能产生bug。在对美国top10网站的调查,压缩可减小21%,而混淆可减小25%。

除了外部脚本和样式,內连的脚本和样式同样应该被压缩。

如果你或许有一打资源,你可能会考虑从一个子域名提供它们的资源服务;为了更好的并行化那许多资源,额外的DNS查询可能是值得的。如果说你有40个资源,可能将那些资源切分到两个子域名是值得的;为了由总数为三个的域名提供你的网站服务,两个额外的DNS查询会是值得的。

5.4 Remove Duplicate Scripts

删除重复的脚本。

在页面中引入相同的脚本两次会伤害性能。可能超出你的预料,美国top10网站的2家有重复脚本引入。两个主要因素造成同一页面引入相同脚本:团队大小和脚本数量。当确实引入重复脚本,会发出不必要的http请求和浪费js执行时间。

发出不必要的http请求发生在IE而不是Firefox。在IE,如果外部脚本引入两次且没有缓存,它会发出2个请求。即使脚本被缓存,刷新时也会发出额外请求。

除了增加http请求,时间被浪费在执行脚本多次上。不管IE还是Firefox都会执行多次。

一种避免多次引入脚本的方法是在模板系统实现一个脚本管理模块。

DNS查询代价很高,因此你需要决定什么才是对你的网站更合适的;承担查询的消耗或者只是由一个域名提供所有服务。

5.5 Minimize DOM Access

最小化DOM访问。

用JS访问DOM元素是缓慢的,所以为了响应更好的页面,你应该:

  • 缓存访问过的元素的引用
  • 在DOM树外更新节点,然后添加到DOM树
  • 避免用JS实现固定布局

很重要的需要记得的是,比方说一旦HTML被请求于foo.com,对那个主机的DNS查询就立即发生了,所以后续的任何对foo.com的请求不再受制于DNS查询。

5.6 Develop Smart Event Handlers

开发聪明的事件处理

有时候页面看起来不那么响应(响应速度慢),是因为绑定到不同元素的大量事件处理函数执行太多次。这是为什么使用事件委托是一种好方法。

另外,你不必等到onload事件来开始处理DOM树,DOMContentLoaded更快。大多时候你需要的只是想访问的元素已在DOM树中,所以你不必等到所有图片被下载。

DNS 预取

6 Images

如果你像我一样想在网站上有一个Twitter小程序,还有网站分析,再也许一些网页字体,那么你必须要链接到一些其它域名,这意味着你将不得不引发DNS查询。我的建议通常是,不要还没有先适当的考虑性能影响就使用某个或任何一个小程序,但对于你认为确实需要的,下面的将很有用……

6.1 Optimize Images

优化图片

在设计师建好图片后,在上传图片到服务器前你仍可以做些事:

  • 检查gif图片的调色板大小是否匹配图片颜色数。
  • 可以把gif转成png看看有没有变小。除了动画,gif一般可以转成png8。
  • 运行pngcrush或其它工具压缩png。
  • 运行jpegtran或其它工具压缩jpeg。

因为这些东西都存在于其它域名,比方说这就意味着你的网站字体CSS将会同你自己的CSS并行下载,从某种意义上说是一种好处,但是脚本将仍会阻塞(除非它们是异步的)

6.2 Optimize CSS Sprites

优化CSS雪碧图

  • 把图片横向合并而不是纵向,横向更小。
  • 把颜色近似的图片合并到一张雪碧图,这样可以让颜色数更少,如果低于256就可以用png8.
  • “Be
    mobile-friendly”并且合并时图片间的间距不要太大。这对图片大小影响不是太大,但客户端解压时需要的内存更少。100×100是10000个像素,1000×1000是1000000个像素。

事实上,这里的问题是DNS查询牵涉到了第三方域名。幸运的是,有一个相当快又简单的办法来加速这个过程:DNS预取。

6.3 Don’t Scale Images in HTML

不要在html中缩放图片

不要因为你可以设置图片的宽高就去用比你需要的大得多的图片。如果你需要

<pre style=”background:#F6F8FA;box-sizing: border-box;word-wrap:
normal;
border-radius: 3px;overflow:auto”><img width=”100″ height=”100″
src=”mycat.jpg” alt=”My Cat” /> </pre>

那么,就用100x100px的图片,而不是500x500px的。

DNS预取所做的恰恰就是凭证领餐(on the
tin),它不能被简单实现。比方说,如果你需要请求来自widget.foo.com的资源,那么你可以通过简单的在页面的<head>里先增加下面这个来预取那个主机的DNS:

6.4 Make favicon.ico Small and Cacheable

favicon.ico小且缓存

favicon.ico是在你服务器根路径的图片。邪恶的是即使你不关心它,浏览器仍然会请求它。所以最好不要响应404。另外由于在同一服务器,每次请求favicon.ico时也会带上cookie。这个图片还会影响下载顺序,比如在IE,如果你在onload时下载额外的组件,fcvicon会在这些组件之前被下载。

怎么减轻favicon.ico的缺点?

  • 小,最好1K以下
  • 设置Expires头部。也许可以安全地设置为几个月。
1 2 3 4 5 <head> ... <link rel="dns-prefetch" href="//widget.foo.com"> ... </head>

7 Mobile

那行简单的内容将会告诉支持的浏览器去开始预取那个域名的DNS,这要稍稍早于它实际需要的时刻。它意味着DNS查询过程,在浏览器<script>元素真正请求小程序的时候就已经在进行中了。这仅仅给浏览器增加了一个很小的开头。

7.1 Keep Components under 25K

保持组件小于25K

这个限制与iPhone不缓存大于25K的组件相关。注意,这是非压缩(uncompressed)的文件大小。在这里minification(压缩,不要与compress混淆)很重要,因为gzip无法满足(iPhone)。

这种简单的链接元素(就是我在CSS魔法上用到的)完全后向兼容,而且不会忽略性能影响。将它看作是性能提升增强吧!

7.2 Pack Components into a Multipart Document

打包组件到一个多部父文档

打包组件到一个多部父文档类似于带附件的邮件。它帮助你在一个http请求中获取多个组件,但注意,iPhone不支持。

延伸阅读

  • 通过预取加速你的网站

资源预取

和DNS预取一样,也可以顺便对你的站点需要的其它资源进行预取。为了弄清楚我们想要预取哪些资源,
首先我们需要了解浏览器通常会在什么时候以什么方式对资源发出请求。

CSS中引用的Web字体和图片表现基本相同;浏览器在碰到需要它们的HTML时开始对它们进行下载。就和我在前面提到那样,浏览器非常聪明,这又是一个例证。想象一下,浏览器一看到下面的CSS声明就开始下载其中所引用的图片:

1 2 3 4 .page--home { background-image:url(home.jpg); } .page--about { background-image:url(about.jpg); } .page--portfolio { background-image:url(portfolio.jpg); } .page--contact { background-image:url(contact.jpg); }

如果浏览器不是等碰到需要这些图片的HTML再下载它们,那么访问主页就会立即下载所有这四个图片。这会造成浪费,所以浏览器一定会确保在需要这些图片时才会开始下载它们。所以,这里有个问题在于,图片下载直到很晚才会开始。

如果我们可以完全确认某个CSS图片肯定会在每个页面都会用到的话,我们就可以用个小把戏让浏览器早早下载好这个图片,无需等到让浏览器碰到需要使用该图片的HTML才开始下载。想做到这一点也非常简单,但所用的方法可能会有点糙,就看你怎么弄了。

比较糙的方法和大多数笨拙的万全之法类似,就是在每个页面放置一个隐藏的<div>,在该div中使用带有空的alt属性的<img>标签。我在CSS
Wizardry项目中的精灵中就是这么干的;因为我知道,每个页面都要使用该精灵,所以我就通过在HTML中对其进行引用对它进行预取。浏览器处理内联(inline)<img>的方式非常好,浏览器会早早地对它们进行预取,所以通过让浏览器将我的精灵作为HTML中的<img>进行载入,浏览器就可以在使用需要精灵的CSS之前将其下载好。通过首先在我的HTML中引用该精灵(隐藏起来的),我就能够抢先把精灵下载好。

还有第二种方法比较优雅,但会让人有些困惑。它和DNS预取的例子非常相似

1 <link rel="prefetch" href="sprite.png">

这会显式地告诉浏览器,马上开始预取我的精灵图片,而不要考虑在它处理CSS时可能会做的任何决定。

令人感到困惑之处在于有两篇文章似乎有不同的观点;基于来自MDN的这篇文章,貌似这种预取指令只是示意浏览器仅在它空闲时有可能会对href所指的资源进行预取。然而,与此矛盾的是,来自Planet
Performance的这篇文章貌似在说,如果浏览器支持rel=prefetch的话,它就一定会预取href中所指的资源,并没有提及是否要在浏览器空闲时才进行预取。我在WebKit的Inpsector中的瀑布图中所看到的情况是后者说得是对的,但是在打开Developer
Tools的情况下(薛定谔测不准。。。)WebKit的表现及其怪异,我就观察不到预取动作的情况了,这也就是我说,我无法100%保证我说的是对的。要是谁能解释清楚这方面的情况,我将不胜感激。

我在前面说过,字体和图片表现非常相似,上面所说的规则同样也适用于字体文件,但你无法使用隐藏的<div>载入字体文件(你需要使用预取link)。

1 <link rel="prefetch" href="webfont.woff">

所以,基本可以这么说,我们这里所作的一切,只能算是让浏览器提前下载资源的小把戏而已,耍了小把戏之后,在浏览器碰到要使用CSS的时候,其中所引用的资源就早已下载好了(或者至少已经在下载中了)。
漂亮极了!

延伸阅读

  • 采用预取来加速你的网站

CSS 与性能

许多建议说,如果你在使用资源域名,你应该由它们提供所有静态资源服务;包括CSS,JS,图片等等。

但是在工作中我们发现一件事,那就是你不应该由一个资源/子域名提供CSS服务…

还记得先前我们讨论CSS块渲染吗?浏览器想尽可能快的获得CSS,直到不能更快;CSS位于你的关键路径。你的关键路径是用户页面请求与之后实际看到页面之间的必要的旅程。因为它阻塞了渲染,所以CSS位于关键路径,而JS和图片不是。你会希望在关键路径上尽可能快的加快这个旅程,这就意味着不能有DNS查询。

实际工作中,我们搭建了一个网站,在某个阶段性的环境中它由同一台主机(如foo.com)提供资源服务,但到了使整个环境支持更加繁忙业务的时候,我们开始由s1.foo.com与s2.foo.com提供资源服务。这意味着所有的图片,JS,CSS,字体等等都来自于不同的域名,由此便引起了DNS查询。这里的问题在于,由于空的缓存,为了获得CSS文件而需要执行DNS查询,这实际上使得关键路径速度彻底慢下来。我们的图片大多数会模糊,这暗示着有理论上不应该有的延时;最佳实践要求应该将资源分布于在子域名上,对吗?但不包括CSS。DNS查询占据了大量的时间,进而延迟了页面的渲染。

因为有这种渲染阻塞阶段,CSS是性能最坏的敌人之一,正如Stoyan
Stefanov阐述的那样
。而且也很有必要注意到浏览器在它开始渲染页面之前将下载所有的CSS。这意味着即使浏览器仅仅在屏幕上渲染页面,也要请求print.css。任何只是基于一种媒体查询的样式表(如<link
rel=stylesheet media=screen and (min-device-width: 800px)
href=desktop.css>)都将会被下载,即使并不需要它们。

即便如此,Andy Davies
告知我WebKit实际上提高了CSS下载的优先级,以便只有渲染页面需要的CSS先到达,而其他的样式,如print.css尽可能的延迟。漂亮!

知道这些关于CSS的信息已经允许我们做出一些决定,这些决定全部基于CSS阻塞渲染,要全部被请求,以及它位于关键路径的知识:

  • 永远不要从一个固定/资源域名提供服务
    因为这会引起DNS查询并进一步延迟渲染。
  • 先提供服务 因此浏览器可以继续忙下去。
  • 合并它
    因为不管怎样浏览器会获取所有CSS,你最好将所有这些压缩于一个HTTP请求。
  • 压缩并简化它 以便浏览器需要下载的少一些。
  • 缓存它的一切 以便上述的过程尽可能少的发生。

CSS位于关键路径,因此你需要尽早先解决它,它阻塞渲染就意味着降低了用户的性能体验。
把CSS移到子域名会损害性能。

延伸阅读

  • CSS与关键路径

压缩与简化

对于你的文本资源,有两个实在很简单的事情是你能(而且也应该)做的;简化他们移除任何注释和空格,并且进一步的压缩它们大小。

如果你想选择其一,单独的压缩要比单独的简化更有效。然而,如果可能的话你应该两个都做。

实施压缩经常需要一点.htaccess诡计,但如我的好朋友 Nick
Payne指出的,.htaccess实际上从服务端的观点来看不是特别有性能;.htaccess评估每一个到达请求,因此实际它有很多开销。

这取自 Apache 文档 :

你应该完全避免使用.htaccess文件,如果你可以直接访问http主服务器的配置文件的话。
使用.htaccess文件使你的Apache http
server慢下来。任何你能包含进一个.htaccess文件的指令最好设置在一个字典
块,因为它具有同样的效用并且有更好的性能。

如果你确实只是访问.htaccess,那么我不会担心;这个开销的代价通常无需关心。实际上通过.htaccess来压缩实现起来很简单。而简化不是那么容易,除非你有一个构建过程,或者用一些类似代码工具套件,或者能直接编译输出最小化的预处理器。

有趣的是,我移动inuit.css到Sass的主要原因最初是——我可以方便的编译一个简化的版本。

简化(Minification)最主要的部分是简单的删除空格与注释;如果你在代码中写的注释像我一样多,那么你确实需要缩减你的资源。

像任何压缩算法一样,压缩(Gzip)将任何基于文本的输入,基于重复的/可重复的字符串对其进行压缩。通过gzip大多数代码压缩得很好,因为所有代码都有包含重复字符串的倾向;例如CSS中一遍又一遍的background-image,标签中一遍又一遍的<strong>…

压缩真的大量的压榨掉资源的大小,你应该明确的启用它。为了能有规范的.htaccess片段,查阅
HTML5 样板处理资源 。

压缩内容引起大量的节约。在写操作的时候,inuit.css
输入有77k大小。压缩以后只有5.52k。简化与压缩给我们节省了93%。而且因为gzip对基于文本的资源工作的很好,你甚至可以压缩可缩放矢量图形(SVGs)和一些字体格式文件!

优化图像

相比通过优化工具运行而言,我对优化图像的艺术不是非常的知识广博,但通过图像自身,后加工来解决是一个相当有趣的话题。

Spriting (精灵)

如果想要一个性能优异的网站,Sprites(精灵,一种网页图片应用处理方式,它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去)是几乎强制性的;在一个HTTP请求里加载一个大的图片,而不是若干个请求若干个图片。但是问题在于,不是所有的图片都可以立即精灵化;可能你有一个图标,需要将它作为一个弹性宽度元素的背景图像,但你显然不能将其精灵化,因为sprites对非固定尺寸元素不起作用。你通常只要在sprite表中的图像周围放许多空格,但这样在sprite中浪费像素它们自己就影响到性能了。

为了解决特定元素的不可精灵化,我们需要一种称为精灵元素的东西。这基本是一个空元素,一般是一个<i>,它的核心工作就是保持空并且加载一个背景图像。

在我创建Sky Bet时我用过这些,YouTube用它们, Facebook用它们, Jonathan
Snook 有 一篇SMACSS的文章整个章节都关于他们。

基本的前提是,如果因为一个元素是流态的而不能精灵化,那么你在它里面放置一个空元素解决尺寸的问题,然后就可以精灵化了,例如:

1 2 3 4 5 <li> <a href="/profile/"> <i></i> Profile </a> </li>

这里我们不能精灵化<li>或者<a>,所以我们在那里有一个空的<i>,它替代加载图标。这是关于性能我最喜欢的事情之一;你正将聪明的技术整合来改善页面速度,却仍然在使用传统的坏标记。有趣的定西!

延伸阅读

  • Sprite还是不要Sprite

视网膜图像

你不需要将所有都提高到视网膜级别。在标准分辨率下,同样的图像放大2倍将包含四倍数量的像素。四倍啊。然而这并不意味着需要通过连接传输四倍的文件大小——感谢图片自身的编码格式——也就是说一旦图像解压并在浏览器中渲染,有四倍数量于平常的像素需要存储于内存。

如果停下来思考一下;视网膜图像最常(即使不是总是)需要用于给手机提供一个保真的UI。手机内存比其他设备少很多。视网膜效果给内存并不很多的设备提供了消耗内存的图像……反复全面的考虑一下你是真的需要视网膜图像,或者还是你可以做出一个明智的妥协?

视网膜效果是一种很棒的,清晰的体验,但如果需要5秒钟时间下载的话,将不会有清爽的体验。在大多数情形速度要胜过美感。

为了给每个人提供足够好的图片,你可以很聪明的给所有设备提供1.5倍的图像,但就我的观点——最好的选择是节俭的使用视网膜。

如果统计数据表明有足够富余,你就可以针对矢量图形优化,或者用字体图标代替位图。在CSS魔法网站我使用了矢量图形,这给我带来了如下好处:

  • 分辨率无关
  • 可简化
  • 可压缩

在工作中 Matt Allen
给我们做了一种字体图标,可以同主要元素一起使用提供一种准视网膜的,可伸缩的图标。

你也可以看看怎样使用类似ReSRC.it的服务,以便基于设备与上下文加载图片。

渐进的 JPGs

性能的一个有趣的方面是感知性能;不是非要你的数字告诉你,而是一个站点感觉起来有多快。

当显示大的JPG图像时,可能你对它的一顿一顿的下载再熟悉不过;图像传输一百个像素,停顿,再五十个,停顿,突然一下子再两百个像素,整个图像加载完毕。

这是JPG图像的传统的工作基准,真的是一种非常卡的体验。通过切换到渐进的JPGs,你能使它们以一种更优异的流行方式加载;它们首次显示的是整个图像,但像素不是很清晰,然后慢慢的聚焦。这听起来比前面的方法要糟糕,但它感觉起来更快;用户立即就有东西可看,而且图像的质量逐渐的提高。典型的这些图像要比它们的基准副本大一点,但是却使整个体验感觉快了许多。

启用渐进的JPGs,你只要简单的在Photoshop中为web与设备保存图像时,检查一下相关的复选项;完工!

网站地图xml地图