前端优化的目的是什么 ?
- 从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更为友好的体验。
- 从服务商角度而言,优化能够减少页面请求数、或者减小请求所占带宽,能够节省可观的资源。
- 总之,恰当的优化不仅能够改善站点的用户体验并且能够节省相当的资源利用。
最终用户响应时间的80-90%用于下载页面中的所有组件:图像,样式表,脚本,Flash等。这是性能黄金规则。
1、尽量减少 HTTP 请求
大部分时间都在下载页面中的所有组件:图像,样式表,脚本,Flash等。减少组件数量反过来减少了呈现页面所需的HTTP请求数量。
以下是一些减少HTTP请求数量的技术:
组合文件
通过将所有脚本组合到单个脚本中来减少HTTP请求数量的方法,并且类似地将所有CSS组合到单个样式表中。
CSS Sprites
CSS Sprites是减少图像请求数量的首选方法。将背景图像合并为单个图像,并使用CSSbackground-image
和background-position
属性显示所需的图像片段。
图像地图
图像地图将多个图像组合成单个图像。整体大小大致相同,但减少HTTP请求的数量会加快页面的速度。图像映射仅在图像在页面中是连续的时才起作用,例如导航栏。
内联图像
内联图像使用data:URL
方案将图像数据嵌入实际页面中。这可以增加HTML文档的大小。将内嵌图像组合到(缓存的)样式表中是一种减少HTTP请求并避免增加页面大小的方法。(并非所有主流浏览器都支持内嵌图像)
2、使用内容分发网络CDN
用户与Web服务器的距离会对响应时间产生影响。在多个地理位置分散的服务器上部署内容将使您的页面从用户的角度加载更快。
内容传送网络(CDN)是分布在多个位置的Web服务器的集合,以更有效地向用户传送内容。选择用于向特定用户传送内容的服务器通常基于网络邻近度的度量。例如,选择具有最少网络跳跃的服务器或具有最快响应时间的服务器。
3、为文件头指定 Expires 或 Cache-Control
这条规则有两个方面:
- 对于静态组件:通过设置远期未来Expires标头实现“永不过期”策略
- 对于动态组件:使用适当的Cache-Control标头来帮助浏览器处理条件请求
网页设计越来越丰富,这意味着页面中有更多的脚本,样式表,图像和Flash。您的页面的首次访问者可能必须发出多个HTTP请求,但通过使用Expires标头,您可以使这些组件可缓存。这可以避免后续页面查看中不必要的HTTP请求。Expires头文件通常与图像一起使用,但它们应该用于所有组件,包括脚本,样式表和Flash组件。
浏览器(和代理)使用缓存来减少HTTP请求的数量和大小,从而加快网页加载速度。Web服务器使用HTTP响应中的Expires头来告诉客户端可以缓存组件多长时间。
4、Gzip压缩文件内容
压缩通过减少HTTP响应的大小来减少响应时间。Gzip是目前最流行、最有效的压缩方法。
尽可能多地压缩文件类型是减轻页面重量和加速用户体验的简便方法。
5、将样式表放在顶部
将样式表放在HEAD中允许页面逐步呈现。
6、把脚本放在底部
脚本带来的问题就是它阻止了页面的平行下载。HTTP/1.1 规范建议,浏览器每个主机名的并行下载内容不超过两个。一个经常用到的替代方法就是使用延迟脚本。
7、避免使用CSS表达式
CSS表达式是一种动态设置CSS属性的强大(且危险)方法。Internet Explorer从第5个版本开始支持CSS表达式。
例如,可以使用CSS表达式将背景颜色设置为每小时交替:
background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" );
8、使用外部 JavaScript 和 CSS
使用外部文件通常会产生更快的页面,因为浏览器会缓存JavaScript和CSS文件。每次请求HTML文档时,都会下载HTML文档中内联的JavaScript和CSS。这减少了所需的HTTP请求数,但增加了HTML文档的大小。另一方面,如果JavaScript和CSS位于浏览器缓存的外部文件中,则HTML文档的大小会减少,而不会增加HTTP请求的数量。
9、减少 DNS 查找
域名系统(DNS)将主机名映射到IP地址,就像电话簿将人们的姓名映射到他们的电话号码一样。当您在浏览器中键入www.yahoo.com时,浏览器联系的DNS解析器将返回该服务器的IP地址。DNS有成本。DNS通常需要20-120毫秒才能查找给定主机名的IP地址。在DNS查找完成之前,浏览器无法从此主机名下载任何内容。
缓存 DNS查找可以改善页面性能。
10、压缩JavaScript和CSS
压缩是从代码中删除不必要的字符以减小其大小从而改善加载时间的做法。缩小代码时,将删除所有注释,以及不需要的空格字符(空格,换行符和制表符)。
11、避免重定向
使用301和302状态代码完成重定向。
要记住的主要事情是重定向会降低用户体验。在用户和HTML文档之间插入重定向会延迟页面中的所有内容,因为页面中的任何内容都无法呈现,并且在HTML文档到达之前不会开始下载任何组件。
12、删除重复的脚本
除了生成浪费的HTTP请求之外,还浪费了多次评估脚本的时间。无论脚本是否可缓存,这种冗余的JavaScript执行都会在Firefox和Internet Explorer中执行。
避免意外包含相同脚本两次的一种方法是在模板系统中实现脚本管理模块。包含脚本的典型方法是在HTML页面中使用SCRIPT标记。
<script type="text/javascript" src="menu_1.0.17.js"></script>
PHP中的另一种选择是创建一个名为的函数insertScript。
<?php insertScript("menu.js") ?>
除了防止多次插入相同的脚本之外,此函数还可以处理脚本的其他问题,例如依赖性检查和向脚本文件名添加版本号以支持远期的Expires头。
13、配置ETag
实体标记(ETag)是Web服务器和浏览器用于确定浏览器缓存中的组件是否与源服务器上的组件匹配的机制。(“实体”是另一个词“组件”:图像,脚本,样式表等)。添加ETag以提供验证比上次修改日期更灵活的实体的机制。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传递回原始服务器。如果ETag匹配,则返回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
14、使Ajax可缓存
Ajax的一个优点是它为用户提供即时反馈,因为它从后端Web服务器异步请求信息。
为了提高性能,优化这些Ajax响应非常重要。提高Ajax性能的最重要方法是使响应可缓存,如添加过期或缓存控制标头中所述。其他一些规则也适用于Ajax:
- Gzip组件
- 减少DNS查找
- 缩小JavaScript
- 避免重定向
- 配置ETag
15、尽早刷新输出缓冲
当用户请求页面时,后端服务器可能需要200到500毫秒才能将HTML页面拼接在一起。在此期间,浏览器在等待数据到达时处于空闲状态。在PHP中,您有函数flush()。它允许您将部分准备好的HTML响应发送到浏览器,以便浏览器可以在后端忙于HTML页面的其余部分时开始获取组件。这种好处主要出现在繁忙的后端或轻量级前端。
16、使用GET进行AJAX请求
在使用时XMLHttpRequest,POST在浏览器中实现为两步过程:首先发送标头,然后发送数据。因此最好使用GET,它只需要一个TCP数据包发送(除非你有很多cookie)。IE中的最大URL长度为2K,因此如果发送的数据超过2K,则可能无法使用GET。
17、推迟加载
JavaScript是理想候选者在onload事件之前和之后拆分的。例如,如果您有执行拖放和动画的JavaScript代码和库,则可以等待,因为在初始渲染之后拖动页面上的元素。其他寻找后期加载候选者的地方包括隐藏内容(用户操作后显示的内容)和首屏下方的图像。
18、预加载组件(提前加载)
通过预加载组件,您可以利用浏览器空闲的时间并请求将来需要的组件(如图像,样式和脚本)。这样,当用户访问下一页时,您可以将大部分组件放在缓存中,并且您的页面将为用户加载更快。
实际上有几种类型的预加载:
- 无条件预加载 :一旦onload触发,你就可以继续获取一些额外的组件。请访问google.com,了解如何请求加载精灵图片。google.com主页上不需要此精灵图片,但在连续搜索结果页面上需要此精灵图片。
- 条件预加载 :基于用户操作,您可以进行有根据的猜测,即用户前进的位置并相应地预加载。在search.yahoo.com上,您可以看到在开始输入输入框后如何请求一些额外的组件。
- 预期的预加载 :在启动重新设计之前提前预加载。经常在重新设计之后听到:“新网站很酷,但比以前慢”。部分问题可能是用户使用完整缓存访问旧网站,但新网站始终是空缓存体验。您可以通过在启动重新设计之前预加载某些组件来缓解此副作用。您的旧站点可以使用浏览器空闲的时间并请求新站点将使用的图像和脚本
19、减少DOM元素的数量
一个复杂的页面意味着需要下载更多数据,同时也意味着JavaScript遍历DOM的效率越慢。比如当你增加一个事件句柄时在500和5000个 DOM元素中循环效果肯定是不一样的。
20、跨域拆分组件 (用域名划分页面内容)
把页面内容划分成若干部分可以使你最大限度地实现平行下载。由于DNS查询惩罚,请确保您使用的域名不超过2-4个。
21、使 frame 数量最少
ifrmae元素可以在父文档中插入一个新的HTML文档。了解iframe如何运作以便有效使用非常重要。
<iframe>
优点:
- 帮助缓慢的第三方内容,如徽章和广告
- 安全沙箱
- 并行下载脚本
<iframe>
缺点:
- 即使空白也要花费
- 阻止页面onload
- 非语义
22、避免404错误
HTTP请求很昂贵,因此发出HTTP请求并获得无用的响应(即404 Not Found)是完全没必要的,并且会在没有任何好处的情况下减慢用户体验。
23、减小Cookie大小
HTTP cookie的使用有多种原因,例如身份验证和个性化。有关cookie的信息在Web服务器和浏览器之间的HTTP标头中进行交换。保持cookie的大小尽可能低是非常重要的,以尽量减少对用户响应时间的影响。
- 消除不必要的cookie
- 保持cookie大小尽可能低,以尽量减少对用户响应时间的影响
- 请注意在适当的域级别设置cookie,以免其他子域受到影响
- 适当地设置过期日期。较早的Expires日期或者没有更早删除cookie,从而改善了用户响应时间
24、对于页面内容使用无coockie域名
当浏览器发出静态图像请求并将cookie与请求一起发送时,服务器对这些cookie没有任何用处。所以他们只是没有充分理由创建网络流量。您应该确保使用无cookie请求去请求静态组件。创建一个子域并在那里托管所有静态组件。
25、最小化DOM访问
使用JavaScript访问DOM元素的速度很慢,因此为了获得响应更快的页面,您应该:
- 缓存对访问元素的引用
- 更新节点“离线”,然后将它们添加到树中
- 避免使用JavaScript修复布局
26、开发智能事件处理程序
有时页面感觉响应性较差,因为过多的事件处理程序附加到DOM树的不同元素,然后执行得太频繁。这就是为什么使用事件委托是一个很好的方法。如果a中有10个按钮div,则只将一个事件处理程序附加到div包装器,而不是每个按钮一个处理程序。事件冒出来,这样你就可以捕捉事件并找出它来自哪个按钮。
您也不需要等待onload事件以便开始使用DOM树执行某些操作。通常,您只需要在树中访问要访问的元素。您不必等待下载所有图像。 DOM Content Loaded是您可能考虑使用的,而不是onload的事件,但是直到它在所有浏览器中都可用。
27、用 <link>
代替 @import
之前的最佳实践之一声明CSS应位于顶部以允许渐进式渲染。在IE中,@import行为与在页面底部使用相同,因此最好不要使用它。
28、避免使用滤镜
IE专有的Alpha Image Loader过滤器旨在解决IE版本<7中的半透明真彩色PNG的问题。该过滤器的问题在于它在下载图像时阻止渲染并冻结浏览器。它还会增加内存消耗,并且每个元素应用,而不是每个图像,因此问题成倍增加。
29、优化图像
设计师完成为您的网页创建图像后,在将这些图像FTP到Web服务器之前,仍然可以尝试一些操作。
- 您可以检查GIF并查看它们是否使用与图像中颜色数对应的调色板大小。使用imagemagick很容易检查
identify -verbose image.gif
当你在调色板中看到使用4种颜色和256色“槽”的图像时,还有改进的余地。 - 尝试将GIF转换为PNG并查看是否存在保存。通常,有。由于浏览器的支持有限,开发人员经常对使用PNG犹豫不决,但现在已成为过去。唯一真正的问题是真彩色PNG中的alpha透明度,但是GIF也不是真彩色,也不支持变量透明度。所以GIF可以做任何事情,调色板PNG(PNG8)也可以做(动画除外)。这个简单的imagemagick命令导致完全安全的PNG:
convert image.gif image.png
- 在所有PNG上 运行pngcrush(或任何其他PNG优化工具)。例:
pngcrush image.png -rem alla -reduce -brute result.png
- 在所有JPEG上运行jpegtran。此工具执行无损JPEG操作(如旋转),还可用于优化和删除图像中的注释和其他无用信息(如EXIF信息)。
jpegtran -copy none -optimize -perfect src.jpg dest.jpg
30、优化CSS Sprites
- 将图像水平排列在精灵中而不是垂直排列通常会导致文件较小。
- 在精灵中组合相似的颜色可以帮助您保持较低的颜色数,理想情况下在256色以下,以适应PNG8。
- 适合移动设备”并且不要在精灵中留下大的间隙。这不会影响文件大小,但需要较少的内存,以便用户代理将图像解压缩为像素图。100x100图像是1万像素,其中1000x1000是100万像素
31、不要在HTML中缩放图像
不要使用比您需要的更大的图像,因为您可以在HTML中设置宽度和高度。如果您需要,
<img width="100" height="100" src="mycat.jpg" alt="My Cat" />
那么您的图像(mycat.jpg)应该是100x100px而不是缩小的500x500px图像。
32、使得favicon.ico尽可能小和可缓存
favicon.ico是一个保留在服务器根目录中的映像。这是一个必要的邪恶,因为即使你不关心它,浏览器仍然会请求它,所以最好不要回复404 Not Found。此外,由于它位于同一台服务器上,因此每次请求时都会发送cookie。此图像也会干扰下载顺序,例如在IE中,当您在onload中请求额外组件时,将在这些额外组件之前下载favicon。
因此,为了减轻拥有favicon.ico的缺点,请确保:
- 它很小,最好不到1K。
- 使用您感觉舒适的设置Expires标头(因为如果您决定更改它,则无法重命名)。您可以在将来几个月安全地设置Expires标头。您可以查看当前favicon.ico的上次修改日期,以做出明智的决定。
33、保持单个内容小于25K
保持单个内容小于25K,这条限制主要是因为iPhone不能缓存大于25K的文件。注意这里指的是解压缩后的大小。由于单纯gizp压缩可能达不要求,因此精简文件就显得十分重要。
34、打包组件成复合文本
将组件打包到多部分文档就像带有附件的电子邮件,它可以帮助您通过一个HTTP请求获取多个组件(请记住:HTTP请求很昂贵)。使用此技术时,首先检查用户代理是否支持它(iPhone不支持)。
35、避免图像空的src和空的href
带有空字符串src属性的图像会出现多个预期。它以两种形式出现:
1.直接的HTML
<img src="">
2.JavaScript的
var img = new Image();
img.src = "";
两种形式都会产生相同的效果:浏览器向您的服务器发出另一个请求
- Internet Explorer向页面所在的目录发出请求。
- Safari和Chrome会向实际页面提出请求。
- Firefox 3及更早版本的行为与Safari和Chrome相同,但3.5版解决了此问题[错误444931],不再发送请求。
- 遇到空图像时,Opera不执行任何操作。
不忘初心,方得始终。