坚信大部分前端工程师者都触碰过yahoo前端开发提升35条标准(https://developer.yahoo.com/performance/rules.html),一些标准人们沒有深层次掌握,可是工作中人们已在使用了。
这35条规则分为content,server,cookie,css,js,image和mobile7个部分,下面就让我们来看一下这些规则:
-
- Content
- Minimize HTTP Requests减少/最小化 http 请求数
- Content
到终端用户的响应时间80%花在前端:大部分用于下载组件 (js/css/image/flash等等)。所以减少请求数量就是页面速度提升的关键,常见的优化方式:
- 资源文件合并打包,一般项目都会在发布的时候进行build,除了文件的编译之外,就是将代码打包成一个文件 (包括js和css)
- 雪碧图,针对背景图片,就是将多图片合并成一个图片,通过background-image 和 background-position 来显示不同部分。
- (个人补充)icon的话,现在可以将icon转化为字体文件,然后通过引用字体的方式来对icon进行引用。
- Inline images。使用data:url scheme来內连图片。这个就相当于把图片转化为scheme来显示
-
-
- Reduce DNS Lookups 减少DNS查询
DNS查询被缓存来提高性能。这种缓存可能发生在特定的缓存服务器(ISP/local area network维护),或者用户的计算机。DNS信息留存在操作系统DNS缓存中(在windows中就是 DNS Client Serve )。大多浏览器有自己的缓存,独立于操作系统缓存。只要浏览器在自己的缓存里有某条DNS记录,它就不会向操作系统发DNS解析请求。
IE默认缓存DNS记录30分钟,FireFox默认缓存1分钟。
当客户端的DNS缓存是空的,DNS查找次数等于页面中的唯一域名数。减少DNS请求数可能会减少并行下载数。避免DNS查找减少响应时间,但减少并行下载数可能会增加响应时间。指导原则是组件可以分散在至少2个但不多于4个的不同域名。这是两者的妥协。
- Avoid Redirects 避免跳转。
检测请求不要出现301或302状态码。最浪费的跳转之一发生在url尾部slash(/)缺失。比如http://test.com/astrology会301跳转到http://test.com/astrology/。
解决方法:可以用Apache等服务器的Alias,mod_rewrite来处理。
- Make Ajax Cacheable 让Ajax请求可以被缓存
异步不代表瞬间,对于时间要求不敏感的数据文件可以使用缓存机制。其方法是:
- gzip组件
- 减少DNS查找
- 压缩JS
- 避免跳转
- 设置ETags
- Post-load Components 延迟加载组件
分析什么是页面初始化必要的,剩下的内容和组件可以延迟加载
- Preload Components 预加载组件
- Reduce DNS Lookups 减少DNS查询
-
预加载看起来与延迟加载相反,但它的确有个不同的目标。通过预加载你可以利用浏览器的空闲时间来请求你将来会用到的组件。这样当用户访问下一个页面时,你会有更多的组件已经在缓存中,这样会极大加快页面加载。
-
-
-
- 无条件预加载:一旦onload触发,你立即获取另外的组件。比如谷歌会在主页这样加载搜索结果页面用到的雪碧图
- 有条件预加载:基于用户动作,你推测用户下一步会去哪里并加载相应组件。
- 预期的预加载:在发布重新设计(的网站)前提前加载。在旧网页预加载新网页的部分组件,那么切换到新网页时就不会是没有任何缓存了
- Reduce the Number of DOM Elements 减少dom数量
dom的数量越多,无论从页面下载,页面渲染都是一种负担,如果你的页面dom数量很多,可以考虑优化页面结构,删除无用dom,或者是通过滚动显示dom的方式来控制画面的dom数量。
- Split Components Across Domains 分散资源文件到不同域名
浏览器对于同域名并发请求是有最大数量限制的,可以通过分散到不同域的方式来让资源文件同时下载数量得到提升,但是由于DNS查询的副作用,建议使用2-4个域名进行分散。
- Minimize the Number of iframes 最小化iframe的数量
- <iframe>优点:
- 帮助解决缓慢的第三方内容的加载,如广告和徽章
- 安全沙盒
- 并行下载脚本
- <iframe>缺点:
- 空的也消耗资源和时间
- 阻塞页面onload
- 非语义化标签
- <iframe>优点:
- No 404s 不要404
http请求是昂贵的,所以发出http请求但获得没用的响应(如404)是完全不必要的,并且会降低用户体验。
-
- Server
- Use a Content Delivery Network 使用CDN
-
用户接近你的服务器会减少响应时间。把你的内容发布到多个,地理上分散的服务器可以让页面加载更快
记住80-90%的终端用户响应时间花费在下载页面中的所有组件:图片、样式、脚本、falsh等等。这是_Performance Golden Rule_。不要从困难的重新设计后台架构开始,最好首先分发你的静态内容。这不仅可以减少响应时间,用CDN还很容易来做。
-
-
- Add an Expires or a Cache-Control Header 加Expires或者Cache-Control头部。
-
这条规则有两个方面:
-
-
-
- 对静态组件:通过设置Expires头部来实现“永不过期”策略。
- 对动态组件:用合适的Cache-Control头部来帮助浏览器进行有条件请求。
-
-
值得注意的是,如果你设置了Expires头部,当组件更新后,你必须更改文件名。
-
-
- Gzip Components 传输时用gzip等压缩组件
一般是在服务器端设置。
- Gzip Components 传输时用gzip等压缩组件
-
gzip一般可减小响应的70%。尽可能去gzip更多(文本)类型的文件。html,脚本,样式,xml和json等等都应该被gzip,而图片,pdf等等不应该被gzip,因为它们本身已被压缩过,gzip它们只是浪费cpu,甚至增加文件大小。
-
-
- Configure ETags 设置ETags
实体标记(Entity tags,ETag)是服务器和浏览器之间判断浏览器缓存中某个组件是否匹配服务器端原组件的一种机制。实体就是组件:图片,脚本,样式等等。ETag被当作验证实体的比最后更改(last-modified)日期更高效的机制。
- Flush the Buffer Early 早一点刷新buffer(尽早给浏览器数据)。
当用户请求一个页面,服务器一般要花200-500ms来拼凑整个页面。这段时间,浏览器是空闲的(等数据返回)。在php,有个方法flush()允许你传输部分准备好的html响应给浏览器。这样的话浏览器就可以开始下载组件,而同时后台可以继续生成页面剩下的部分。这种好处更多是在忙碌的后台或轻前端网站可以看到。
- Use GET for AJAX Requests ajax请求用get。
当使用XMLHttpRequest,POST 被浏览器实现为两步:首先发送头部,然后发送数据。所以使用GET最好,仅用一个TCP包发送(除非cookie太多)。IE的url长度限制是2K。
- Configure ETags 设置ETags
-
从语义上讲,获取数据应该用GET,提交数据到服务器用POST。Avoid Empty Image src 避免空src的图片。空图片标签,浏览器会向你的服务器发请求,同样问题也会出现在:
<script src=""><link href="">
-
- Cookie
- Reduce Cookie Size
由于每次发请求都会将cookie的信息通过http的header在浏览器和服务器端交换,所以应当减小cookie的大小来降低响应时间。
- 消除不必要的cookie
- 尽可能减小cookie的大小来降低响应时间
- 注意设置cookie到合适的域名级别,则其它子域名不会被影响
- 正确设置Expires日期。早一点的Expires日期或者没有会尽早删除cookie,优化响应时间
- 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的静态组件请求。
- Reduce Cookie Size
- CSS
- Put Stylesheets at the Top 把样式放在顶部。
研究雅虎网页性能时发现把样式表移到<head>里会让页面更快。这是因为把样式表移到<head>里允许页面逐步渲染。
把样式表放在文档底部的问题是它阻止了许多浏览器的逐步渲染,包括IE。这些浏览器阻止渲染来避免在样式更改时需要重绘页面元素。所以用户会卡在白屏。
- Avoid CSS Expressions 避免CSS表达式。
CSS表达式是强大的(可能也是危险的)设置动态CSS属性的方法。
background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" );
- Choose <link> over @import 选择<link>而不是@import。
原理同CSS应该在顶部来允许逐步渲染。
- Avoid Filters 避免使用(IE)过滤器。
最佳做法是放弃AlphaImageLoader,改用PNG8来优雅降级。
- Put Stylesheets at the Top 把样式放在顶部。
- JavaScript
- Put Scripts at the Bottom 把脚本放到底部。
脚本引起的问题是它们阻塞了并行下载。如果你的图片分散在不同服务器,那么你能并行下载多个图片。但当脚本在下载,浏览器不会再下载其它组件,即使在不同域名下。
- Make JavaScript and CSS External 使用外部JS和CSS。
使用外部文件一般会加快页面,因为JS和CSS文件被浏览器缓存了。內联的JS和CSS在每次HTML文档下载时都被下载。內联减少了http请求,但增加了HTML文档大小。同时,如果JS和CSS被缓存了,那么HTML文档可以减小大小而不增加HTTP请求。
核心因素,就是JS和CSS被缓存相对于HTML文档被请求的频率。尽管这个因素很难被量化,但可以用不同的指标来计算。如果网站用户每个session有多个pv,许多页面重用相同的JS和CSS,那么有很大可能用外部JS和CSS更好。
- Minify JavaScript and CSS 压缩JS和CSS。
更小的体积,更快的请求时间,压缩就是删除代码中不必要的字符来减小文件大小,从而提高加载速度。当代码压缩时,注释删除,不需要的空格(空白,换行,tab)也被删除。
混淆容易出bug,个人主观经验,不要使用混淆。
- Remove Duplicate Scripts 删除重复的脚本。
两个主要因素造成同一页面引入相同脚本:团队大小和脚本数量。当确实引入重复脚本,会发出不必要的http请求和浪费js执行时间。
一种避免多次引入脚本的方法是在模板系统实现一个脚本管理模块。
类似现在使用的React和Vue框架的时候经常会用到的性能优化方法按需加载非常相似,对应到Angular终究是按需注入。
- Minimize DOM Access 最小化DOM访问。用JS访问DOM元素是缓慢的,应该:
- 缓存访问过的元素的引用
- 在DOM树外更新节点,然后添加到DOM树
- 避免用JS实现固定布局
- Put Scripts at the Bottom 把脚本放到底部。
- Cookie
PS:现在的Vue和React就是使用Virtual DOM(VDOM),将画面结构存在JS中,在JS处理画面变更,待所有画面变更结束后,将VDOM渲染到真实的DOM上。
Develop Smart Event Handlers 开发聪明的事件处理
有时候页面响应速度慢,是因为绑定到不同元素的大量事件处理函数执行太多次。这是为什么使用_事件委托_是一种好方法。
// 想要在获取每个li的点击事件,可以将点击事件绑定在ul上,// 这样通过事件冒泡的方式就能够获取所有li的点击了<ul click='test()'> <li></li> <li></li> <li></li></ul>
另外,你不必等到onload事件来开始处理DOM树,DOMContentLoaded更快。大多时候你需要的只是想访问的元素已在DOM树中,所以你不必等到所有图片被下载
- Images
- Optimize Images 优化图片
- 可以把gif转成png看看有没有变小。除了动画,gif一般可以转成png8。
- 运行pngcrush或其它工具压缩png。
- 运行jpegtran或其它工具压缩jpeg。
- Optimize CSS Sprites 优化CSS雪碧图
- 把图片横向合并而不是纵向,横向更小。
- 把颜色近似的图片合并到一张雪碧图,这样可以让颜色数更少,如果低于256就可以用png8.
- "Be mobile-friendly"并且合并时图片间的间距不要太大。这对图片大小影响不是太大,但客户端解压时需要的内存更少。100×100是10000个像素,1000×1000是1000000个像素。
- Don't Scale Images in HTML 不要在html中缩放图片
不要因为你可以设置图片的宽高就去用比你需要的大得多的图片。因为请求大的图片的资源消耗是大于请求小尺寸的图片的。
- Make favicon.ico Small and Cacheable favicon.ico小且缓存
favicon.ico是在你服务器根路径的图片,浏览器无论在什么时候都会请求这个图片,所以:
- 小,最好1K以下
- 设置Expires头部。也许可以安全地设置为几个月。
- Optimize Images 优化图片
- Mobile
- Keep Components under 25K 保持组件小于25K
这个限制与iPhone不缓存大于25K的组件相关。注意,这是非压缩(uncompressed)的文件大小。在这里minification(压缩,不要与compress混淆)很重要,因为gzip无法满足(iPhone)
- Pack Components into a Multipart Document 打包组件到一个多部父文档
打包组件到一个多部父文档类似于带附件的邮件。它帮助你在一个http请求中获取多个组件,但注意,iPhone不支持。
- Keep Components under 25K 保持组件小于25K
本文来源于:前端性能优化(基础篇)-变化吧门户
特别声明:以上文章内容仅代表作者本人观点,不代表变化吧门户观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。
- 赞助本站
- 微信扫一扫
- 加入Q群
- QQ扫一扫
评论