前端性能提升--雅虎35条军规

          

摘要:无论是在工作中,还是在面试中,web前端性能的优化都是很重要的,那么我们进行优化需要从哪些方面入手呢?可以遵循雅虎的前端优化34条军规,不过现在已经是35条了,所以可以说是雅虎前端优化的35条军规。已分类,挺好的,这样对于优化有一个比较清晰的方向
                  


                                                  内容部分


1.尽可能的减少http请求数

当你打开网页的时候 所看到的文字图片多媒体等 都是从服务器获取的 每一个内容的获取 就是http请求

  •  图片合并
  • js合并(一般合并到3~5个,css类似)
  • css合并

2.减少DNS查询

如:用户打开 www.a.com 这个网址时 计算机是不知道它是什么、在哪里 必须通过一种转换机制才能到达这个页面
这种机制能够将 www.a.com 对应到一个IP地址 10.96.141.1(一个计算机理解的地址)
在通过这个IP地址(使用DNS查找)对应到 www.a.com 这个网站
整个过程就是DNS查找过程

查找的过程中浏览器是得不到任何资源的(这期间浏览器是一片空白)
所以要对这个过程进行缓存 缓存之后就可以减少这种查找过程

不同浏览区缓存时间不同 (IE:30m 火狐:60s 谷歌:60s)
当缓存时间长时:减少DNS的重复查找 节省时间
当缓存时间短时:浏览器会及时检查网站服务器的变化 保证正确性

根据自身情况进行缓存时间的长短
多域:网址 图片 js 分别使用不同的域名
单域:网址 图片 js 使用同一域名
  • 不要在一个网站中有太多域(2到4个主机刚好,这是同时减少DNS查找和允许高并发下载的折中方案)
  • 用到CDN静态服务器
  • DNS预解析
// DNS 预解析
<mate http-equiv="x-dns-prefetch-control" content="on"/>
<link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
<link rel="dns-prefetch" href="http://nsclinck.baidu.com" />

3.避免重定向

重定向:用户原始请求被重新转向到了其他请求(用户想访问的页面a 被重新 指向了页面b)
重定向状态码:
301 Moved Permanently:用户请求的页面被移动到另外的位置(永久重定向)
302 Found:用户请求的页面被找到了但不在原始位置(临时重定向)
对用户没有什么影响 但对搜索引擎影响就大了 都是从a 跳到 b
301 会识别一次 第二次就会直接跳到 b
302 每次都是 先找a 再跳到 b

为什么避免重定向

无论301还是302都增加了服务器的往返次数
当用户发起访问 a 网站的请求时 服务器收到 由于a 重定向到 b 所以服务器返回一个重定向信息(301 或 302)
并把这个信息写在 header 中 并在 header 中返回一个新的地址(b 的地址)
但是body中是空白的 用户端在收到这个反馈后 就知道地址改了
所以用户的浏览器会再一次请求 请求到b 然后才打开网页 下载资源
用户多了一次获取新地址的过程 必然会增加浏览器到服务器的返回次数
(要尽量减少Http请求 所以要避免使用)

有一种常见的极其浪费资源的重定向,而且web开发人员一般都意识不到这一点,就是URL尾部缺少一个斜线的时候。例如,跳转到http://astrology.yahoo.com/astrology会返回一个重定向到http://astrology.yahoo.com/astrology/的301响应(注意添在尾部的斜线)。在Apache中可以用Aliasmod_rewrite或者DirectorySlash指令来取消不必要的重定向。

  重定向最常见的用途是把旧站点连接到新的站点,还可以连接同一站点的不同部分,针对用户的不同情况(浏览器类型,用户帐号类型等等)做一些处理。用重定向来连接两个网站是最简单的,只需要少量的额外代码。虽然在这些时候使用重定向减少了开发人员的开发复杂度,但降低了用户体验。一种替代方案是用Aliasmod_rewrite,前提是两个代码路径都在相同的服务器上。如果是因为域名变化而使用了重定向,就可以创建一条CNAME(创建一个指向另一个域名的DNS记录作为别名)结合Alias或者mod_rewrite指令。

4.使用ajax缓存

ajax:不重新加载页面的情况下 使客户端与服务器交换数据 可使网站数据分批加载 也可局部更新

    post:每次都执行 不能被缓存
    get:同一地址不重复执行 可以被缓存

5.延迟加载组件

  可以凑近看看页面并问自己:什么才是一开始渲染页面所必须的?其余内容都可以等会儿。

  JavaScript是分隔onload事件之前和之后的一个理想选择。例如,如果有JavaScript代码和支持拖放以及动画的库,这些都可以先等会儿,因为拖放元素是在页面最初渲染之后的。其它可以延迟加载的部分包括隐藏内容(在某个交互动作之后才出现的内容)和折叠的图片。

  工具可帮你减轻工作量:YUI Image Loader可以延迟加载折叠的图片,还有YUI Get utility是一种引入JS和CSS的简单方法。Yahoo!主页就是一个例子,可以打开Firebug的网络面板仔细看看。

  最好让性能目标符合其它web开发最佳实践,比如“渐进增强”。如果客户端支持JavaScript,可以提高用户体验,但必须确保页面在不支持JavaScript时也能正常工作。所以,在确定页面运行正常之后,可以用一些延迟加载脚本增强它,以支持一些拖放和动画之类的华丽效果。

6.预加载组件

  预加载可能看起来和延迟加载是相反的,但它其实有不同的目标。通过预加载组件可以充分利用浏览器空闲的时间来请求将来会用到的组件(图片,样式和脚本)。用户访问下一页的时候,大部分组件都已经在缓存里了,所以在用户看来页面会加载得更快。

实际应用中有以下几种预加载的类型:

  • 无条件预加载——尽快开始加载,获取一些额外的组件。google.com就是一个sprite图片预加载的好例子,这个sprite图片并不是google.com主页需要的,而是搜索结果页面上的内容。
  • 条件性预加载——根据用户操作猜测用户将要跳转到哪里并据此预加载。在search.yahoo.com的输入框里键入内容后,可以看到那些额外组件是怎样请求加载的。
  • 提前预加载——在推出新设计之前预加载。经常在重新设计之后会听到:“这个新网站不错,但比以前更慢了”,一部分原因是用户访问先前的页面都是有旧缓存的,但新的却是一种空缓存状态下的体验。可以通过在将要推出新设计之前预加载一些组件来减轻这种负面影响,老站可以利用浏览器空闲的时间来请求那些新站需要的图片和脚本。

7.减少DOM元素的数量

  一个复杂的页面意味着要下载更多的字节,而且用JavaScript访问DOM也会更慢。举个例子,想要添加一个事件处理器的时候,循环遍历页面上的500个DOM元素和5000个DOM元素是有区别的。

  大量的DOM元素是一种征兆——页面上有些内容无关的标记需要清理。正在用嵌套表格来布局吗?还是为了修复布局问题而添了一堆的<div>?或许应该用更好的语义化标记。

YUI CSS utilities对布局有很大帮助:grids.css针对整体布局,fonts.css和reset.css可以用来去除浏览器的默认格式。这是个开始清理和思考标记的好机会,例如只在语义上有意义的时候使用<div>,而不是因为它能够渲染一个新行。

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

document.getElementsByTagName('*').length

 

  那么多少DOM元素才算是太多呢?可以参考其它类似的标记良好的页面,例如Yahoo!主页是一个相当繁忙的页面,但只有不到700个元素(HTML标签)。

8.跨域分离组件

  分离组件可以最大化并行下载,但要确保只用不超过2-4个域,因为存在DNS查找的代价。例如,可以把HTML和动态内容部署在www.example.org,而把静态组件分离到static1.example.orgstatic2.example.org

9.尽量少用iframe

  用iframe可以把一个HTML文档插入到父文档里,重要的是明白iframe是如何工作的并高效地使用它。

<iframe>的优点:

  • 引入缓慢的第三方内容,比如标志和广告
  • 安全沙箱
  • 并行下载脚本

<iframe>的缺点:

  • 代价高昂,即使是空白的iframe
  • 阻塞页面加载
  • 非语义

10.杜绝404

  HTTP请求代价高昂,完全没有必要用一个HTTP请求去获取一个无用的响应(比如404 Not Found),只会拖慢用户体验而没有任何好处。

  有些站点用的是有帮助的404——“你的意思是xxx?”,这样做有利于用户体验,,但也浪费了服务器资源(比如数据库等等)。最糟糕的是链接到的外部JavaScript有错误而且结果是404。首先,这种下载将阻塞并行下载。其次,浏览器会试图解析404响应体,因为它是JavaScript代码,需要找出其中可用的部分。

 

 


                                                  css部分


11.将css放在页面最上面

Cascading Style Sheets(层叠样式表单)
为了提高浏览器的渲染性能 避免页面空白或闪烁的问题

12.避免在CSS中使用Expressions

什么是css Expressions:
css Expressions 俗称 css表达式
是用来把css属性 和 js表达式关联起来
(这里的css属性可以是固有属性 也可以是自定义属性
就是说css属性后面可以是js表达式 css的值 = js表达式计算的结果)
css Expressions 计算频率很高
在页面显示和缩放、页面滚动、鼠标移动的时候都会从新计算一次

所有使用css Expressions 浏览器会不停的计算 以至于严重影响性能 及 用户体验

从IE5开始支持,但从IE8起就不推荐使用了。例如,可以用CSS表达式把背景颜色设置成按小时交替的:

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

13.选择<link>舍弃@import

  前面提到了一个最佳实践:为了实现逐步渲染,CSS应该放在顶部。

  在IE中用@import与在底部用<link>效果一样,所以最好不要用它

14.避免使用滤镜

  IE专有的AlphaImageLoader滤镜可以用来修复IE7之前的版本中半透明PNG图片的问题。在图片加载过程中,这个滤镜会阻塞渲染,卡住浏览器,还会增加内存消耗而且是被应用到每个元素的,而不是每个图片,所以会存在一大堆问题。

最好的方法是干脆不要用AlphaImageLoader,而优雅地降级到用在IE中支持性很好的PNG8图片来代替。如果非要用AlphaImageLoader,应该用下划线hack:_filter来避免影响IE7及更高版本的用户。


                                                   js部分


15.把script放在页面最底部

    如果js出现问题 不会出现空白影响用户浏览

16.移除重复的脚本

IE会产生不必要的HTTP请求,而Firefox不会。在IE中,如果一个不可缓存的外部脚本被页面引入了两次,它会在页面加载时产生两个HTTP请求。即使脚本是可缓存的,在用户重新加载页面时也会产生额外的HTTP请求。

除了产生没有意义的HTTP请求之外,多次对脚本求值也会浪费时间。因为无论脚本是否可缓存,在Firefox和IE中都会执行冗余的JavaScript代码。

避免不小心把相同脚本引入两次的一种方法就是在模版系统中实现脚本管理模块。典型的脚本引入方法就是在HTML页面中用SCRIPT标签:

<script type="text/javascript" src="menu_1.0.17.js"></script>

17.尽量减少DOM访问

用JavaScript访问DOM元素是很慢的,所以,为了让页面反应更迅速,应该:

  • 缓存已访问过的元素的索引
  • 先“离线”更新节点,再把它们添到DOM树上
  • 避免用JavaScript修复布局问题

18.用智能的事件处理器

  有时候感觉页面反映不够灵敏,是因为有太多频繁执行的事件处理器被添加到了DOM树的不同元素上,这就是推荐使用事件委托的原因。如果一个div里面有10个按钮,应该只给div容器添加一个事件处理器,而不是给每个按钮都添加一个。事件能够冒泡,所以可以捕获事件并得知哪个按钮是事件源。


                                               css和js部分


19.把JS和CSS放到外部文件中

单独提取优点:
提高了js和css的复用性 减少页面体积 提高js和css的可维护性

写在页面里优点:
减少页面请求数  提升页面渲染速度

应该写在页面内的情况

  • js和css只应用于一个页面
  • 一个不经常被访问的页面
  • 脚本和样式很少的情况(不多于20、30行)

20.压缩 JavaScript 和 CSS

1、去除不必要的空白符、格式符、注释(代码格式化)
2、简写方法名参数名压缩js脚本

建议:在正式上线前 将js、css都进行压缩 使线上版本是最轻量级的 大幅提升网址性能

两个最常用的JavaScript代码压缩工具是JSMin和YUI Compressor,YUI compressor还可以压缩CSS。除了压缩外部脚本和样式,行内的<script><style>块也可以压缩。即使启用了gzip模块,先进行压缩也能够缩小5%或者更多的大小。JavaScript和CSS的用处越来越多,所以压缩代码会有不错的效果。


                                                   图片部分


21.优化图片

  • 尝试把GIF格式转换成PNG格式,看看是否节省空间。在所有的PNG图片上运行pngcrush(或者其它PNG优化工具)

22.优化CSS Sprite

  • 在Sprite图片中横向排列一般都比纵向排列的最终文件小
  • 组合Sprite图片中的相似颜色可以保持低色数,最理想的是256色以下PNG8格式
  • “对移动端友好”,不要在Sprite图片中留下太大的空隙。虽然不会在很大程度上影响图片文件的大小,但这样做可以节省用户代理把图片解压成像素映射时消耗的内存。100×100的图片是1万个像素,而1000×1000的图片就是100万个像素了。

23.不要用HTML缩放图片

  不要因为在HTML中可以设置宽高而使用本不需要的大图。如果需要

<img width="100" height="100" src="mycat.jpg" alt="My Cat" />

  那么图片本身(mycat.jpg)应该是100x100px的,而不是去缩小500x500px的图片。

24.用小的可缓存的favicon.ico(P.S. 收藏夹图标)

  favicon.ico是放在服务器根目录的图片,它会带来一堆麻烦,因为即便你不管它,浏览器也会自动请求它,所以最好不要给一个404 Not Found响应。而且只要在同一个服务器上,每次请求它时都会发送cookie,此外这个图片还会干扰下载顺序,例如在IE中,当你在onload中请求额外组件时,将会先下载favicon。

所以为了缓解favicon.ico的缺点,应该确保:

  • 足够小,最好在1K以下
  • 设置合适的有效期HTTP头(以后如果想换的话就不能重命名了),把有效期设置为几个月后一般比较安全,可以通过检查当前favicon.ico的最后修改日期来确保变更能让浏览器知道。

                                               cookie部分

25.给Cookie减肥

  使用cookie的原因有很多,比如授权和个性化。HTTP头中cookie信息在web服务器和浏览器之间交换。重要的是保证cookie尽可能的小,以最小化对用户响应时间的影响。

  • 清除不必要的cookie
  • 保证cookie尽可能小,以最小化对用户响应时间的影响
  • 注意给cookie设置合适的域级别,以免影响其它子域
  • 设置合适的有效期,更早的有效期或者none可以更快的删除cookie,提高用户响应时间

26.把组件放在不含cookie的域下

  当浏览器发送对静态图像的请求时,cookie也会一起发送,而服务器根本不需要这些cookie。所以它们只会造成没有意义的网络通信量,应该确保对静态组件的请求不含cookie。可以创建一个子域,把所有的静态组件都部署在那儿。

  如果域名是www.example.org,可以把静态组件部署到static.example.org。然而,如果已经在顶级域example.org或者www.example.org设置了cookie,那么所有对static.example.org的请求都会含有这些cookie。这时候可以再买一个新域名,把所有的静态组件部署上去,并保持这个新域名不含cookie。Yahoo!用的是yimg.com,YouTube是ytimg.com,Amazon是images-amazon.com等等。

  把静态组件部署在不含cookie的域下还有一个好处是有些代理可能会拒绝缓存带cookie的组件。有一点需要注意:如果不知道应该用example.org还是www.example.org作为主页,可以考虑一下cookie的影响。省略www的话,就只能把cookie写到*.example.org,所以因为性能原因最好用www子域,并且把cookie写到这个子域下。


                                                   移动端


27.保证所有组件都小于25K

  这个限制是因为iPhone不能缓存大于25K的组件,注意这里指的是未压缩的大小。这就是为什么缩减内容本身也很重要,因为单纯的gzip可能不够。

28.把组件打包到一个复合文档里

  把各个组件打包成一个像有附件的电子邮件一样的复合文档里,可以用一个HTTP请求获取多个组件(记住一点:HTTP请求是代价高昂的)。用这种方式的时候,要先检查用户代理是否支持(iPhone就不支持)。

 


                                                服务器部分


29.使用CND(内容分发网络)     。。。每一台需要钱来支持。。。

 CDN通俗来说就是在离你最近的地方,放置一台性能好链接顺畅的副本服务器,让你能够以最近的距离,最快的速度获取内容。

30.添加Expire/ Cache-Control头(可以通过修改.htaccess文件来实现)

Apache开启了expire模块,当浏览器发送资源请求的时候 Apache返回资源的同时 会返回一个名为expire的Http头

expire头的内容是一个时间值 值就是资源在本地的过期时间、这个值会存在本地
在本地缓存阶段找到一个本地对应的资源值
当前时间还没超过资源的过期时间 就直接使用这一个资源 不会发送Http请求

Cache-Control
是Http协议中常用的头部之一,顾名思义 它是负责控制页面的缓存机制 如果该头部指示缓存缓存的内容也会存在本地, 操作流程和expire相似  ,但也有不同的地方 ,cache-control有更多的选项,而且也有更多的处理方式

简言之就是:   Expire设置本地缓存时间           Cache-Control设置本地缓存

  • 对于静态内容:设置文件头过期时间Expires的值为“Never expire”(永不过期)或者设置一个遥远的将来时间
  • 对于动态内容:使用恰当的cache-Control文件头来帮助浏览器进行有条件的请求
  • Etag是可以动态调的更加灵活,而这个是设了多久就是多久,记得加上版本号。

 网页设计越来越丰富,这意味着页面里有更多的脚本,图片和Flash。站点的新访客可能还是不得不提交几个HTTP请求,但通过使用有效期能让组件变得可缓存,这避免了在接下来的浏览过程中不必要的HTTP请求。有效期HTTP头通常被用在图片上,但它们应该用在所有组件上,包括脚本、样式和Flash组件。

  浏览器(和代理)用缓存来减少HTTP请求的数目和大小,让页面能够更快加载。web服务器通过有效期HTTP响应头来告诉客户端,页面的各个组件应该被缓存多久。用一个遥远的将来时间做有效期,告诉浏览器这个响应在2010年4月15日前不会改变。

1

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

 如果你用的是Apache服务器,用ExpiresDefault指令来设置相对于当前日期的有效期。下面的例子设置了从请求时间起10年的有效期:

ExpiresDefault "access plus 10 years"

31.启用Gzip压缩

什么是Gzip压缩:文件先放服务器压缩 然后在存储 存储完毕以后 浏览器在对压缩过得内容进行解压缩 并执行
目前的浏览器都能很好的支持Gzip
所有的文本内容都要进行Gzip压缩

前端工程师可以想办法明显地缩短通过网络传输HTTP请求和响应的时间。毫无疑问,终端用户的带宽速度,网络服务商,对等交换点的距离等等,都是开发团队所无法控制的。但还有别的能够影响响应时间的因素,压缩可以通过减少HTTP响应的大小来缩短响应时间。

从HTTP/1.1开始,web客户端就有了支持压缩的Accept-Encoding HTTP请求头。

1

Accept-Encoding: gzip, deflate

  如果web服务器看到这个请求头,它就会用客户端列出的一种方式来压缩响应。web服务器通过Content-Encoding相应头来通知客户端。

1

Content-Encoding: gzip

  尽可能多地用gzip压缩能够给页面减肥,这也是提升用户体验最简单的方法。

32.配置实体标签(ETag)

全称Entity Tag(实体标签) 它包含在响应头部中 属于Http协议 受web服务支持
它是使用特殊字符串 来标识某个请求资源版本

当用户通过浏览器来服务器请求资源的时候 服务器会进行比较
如果两边的ETag一致 那就代表浏览器和服务器的ETag一致 这就意味着该资源没有修改过 和以前是一样的
这时候服务器会返回一个304码 告诉浏览器对比一致 可以使用本地缓存的版本 会帮助服务器减轻很多负担
这就是配置ETag的好处

  实体标签(ETags),是服务器和浏览器用来决定浏览器缓存中组件与源服务器中的组件是否匹配的一种机制(“实体”也就是组件:图片,脚本,样式表等等)。添加ETags可以提供一种实体验证机制,比最后修改日期更加灵活。一个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传回源服务器。如果ETags匹配成功,会返回一个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

etag详解可看https://blog.csdn.net/badfraud/article/details/79759679

33.避免图片src属性为空

Image with empty string src属性是空字符串的图片很常见,主要以两种形式出现:

1.straight HTML

<img src=””>

2.JavaScrip

var img = new Image();
img.src = “”;

这两种形式都会引起相同的问题:浏览器会向服务器发送另一个请求。

34.尽早清空缓冲区

 当用户请求一个页面时,服务器需要用大约200到500毫秒来组装HTML页面,在这期间,浏览器闲等着数据到达。PHP中有一个flush()函数,允许给浏览器发送一部分已经准备完毕的HTML响应,以便浏览器可以在后台准备剩余部分的同时开始获取组件,好处主要体现在很忙的后台或者很“轻”的前端页面上(P.S. 也就是说,响应时耗主要在后台方面时最能体现优势)。

  较理想的清空缓冲区的位置是HEAD后面,因为HTML的HEAD部分通常更容易生成,并且允许引入任何CSS和JavaScript文件,这样就可以让浏览器在后台还在处理的时候就开始并行获取组件。

例如:

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

35.对Ajax用GET请求

  Yahoo!邮箱团队发现使用XMLHttpRequest时,浏览器的POST请求是通过一个两步的过程来实现的:先发送HTTP头,在发送数据。所以最好用GET请求,它只需要发送一个TCP报文(除非cookie特别多)。IE的URL长度最大值是2K,所以如果要发送的数据超过2K就无法使用GET了。

POST请求的一个有趣的副作用是实际上没有发送任何数据,就像GET请求一样。正如HTTP说明文档中描述的,GET请求是用来检索信息的。所以它的语义只是用GET请求来请求数据,而不是用来发送需要存储到服务器的数据。

 

 

 

转载自:https://www.cnblogs.com/xianyulaodi/p/5755079.html,其中根据慕课里的雅虎军规视频对某些内容做出了添加修改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值