More Related Content Similar to After Yahoo 34 Rules -- 网站性能优化新进展 (7) After Yahoo 34 Rules -- 网站性能优化新进展5. 1.2 HTML被解析成Dom树 (X)HTML文档是一份不那么严谨的XML(文本)文档,没有Schema, 有DTD(通常在HTML文本第一行Doctype中定义) 浏览器按照文档内容自上而下解释运行展现.最终被完整的解析成一颗树(DOM树): 其余的HTTP请求,除了CSS可以引入背景图和XHR(以后会介绍)之外几乎都是在解析HTML时,由树上的几种特定节点发起的: <img>:用来嵌入图片(jpg,png,gif.) <iframe>:用来嵌入其他HTML <link>:可以用来引入CSS文件,同时CSS内容引入背景图请求 <script>:可以用来引入JavaScript文件 <object>和<embed>:通常用来引入Flash文件 5 6. 1.2 HTML被解析成Dom树 (X)HTML文档是一份不那么严谨的XML(文本)文档,没有Schema, 有DTD(通常在HTML文本第一行Doctype中定义) 浏览器按照文档内容自上而下解释运行展现.最终被完整的解析成一颗树(DOM树): 其余的HTTP请求,除了CSS可以引入背景图和XHR(以后会介绍)之外几乎都是在解析HTML时,由树上的几种特定节点发起的: <img>:用来嵌入图片(jpg,png,gif.) <iframe>:用来嵌入其他HTML <link>:可以用来引入CSS文件,同时CSS内容引入背景图请求 <script>:可以用来引入JavaScript文件 <object>和<embed>:通常用来引入Flash文件 6 Dom节点的多少也决定了,HTML解析的速度 需要发送请求的Dom节点数,决定了HTTP请求个数 Dom节点的顺序也有讲究. 7. a.css文件的内容: .myTxt {color:red;font-size:50px} 各种CSS定义驻留在Dom树的属性中或元素节点内.仍然是Dom树的一部分 1.3 使用CSS定义显示样式 如何定义字体颜色大小,区块的边框内外变距? <span><font size="50" color="red">CSS出现之前</font></span> <span style="color:red,font-size:50px">CSS使用Style属性直接定义</span> <span class="myTxt">使用Class等多种方式外部定义</span> 在HTML内定义 <style> .myTxt {color:red;font-size:50px} </style> 通过<link>引入CSS文件,在文件中定义 <link rel="stylesheet" type="text/css" href="http://a.com/a.css" /> 7 8. 1.3 使用CSS定义显示样式 如何定义字体颜色大小,区块的边框内外变距? <span><font size="50" color="red">CSS出现之前</font></span> <span style="color:red,font-size:50px">CSS使用Style属性直接定义</span> <span class="myTxt">使用Class等多种方式外部定义</span> 在HTML内定义 <style> .myTxt {color:red;font-size:50px} </style> 通过<link>引入CSS文件,在文件中定义 <link rel="stylesheet" type="text/css" href="http://a.com/a.css" /> CSS的类意味着:每个类定义的影响范围覆盖所有Dom节点. 最佳的方式是有展现的在Dom节点出现前定义好CSS. 另外CSS的背景图等属性也会引入图片HTTP请求. a.css文件的内容: .myTxt {color:red;font-size:50px} 各种CSS定义驻留在Dom树的属性中或元素节点内.仍然是Dom树的一部分 8 12. 1.5 DHTML--JavaScript改变DOM树 JavaScript不满足于简单的计算,校验和事件响应. 浏览器将其内的Dom树为转化JS可以访问和操作的对象. 由事件或时间线驱动JS响应的方法对Dom树进行修改.称D(Dynamic)HTML W3C(万维网联盟)的 Dom Level 1,2&3中定义了3个层次一系列Dom上的操作接口. http://www.w3.org/DOM/DOMTR 在各种浏览器下Level 1基本都能被正确实现.IE有独特的事件模型.其余浏览器的事件模型符合W3C定义 12 因为JavaScript可以改变DomTree 所以HTML在解析Dom时遇到<script>节点时会等待其加载和执行被阻滞 13. 1.6 AJAX--JavaScript与服务器端交互 JavaScript已经具有能力完全的改变所在网页的每个细节. JavaScript的野心不止于此,如果JS能由事件驱动,从服务器端源源不断的获取新鲜数据,那理论上不再需要第二个页面了. 网页上一切来自HTTP,获取数据自然需要JavaScript发起HTTP,接收并理解响应. 于是有了XHR(XmlHttpRequest),首先作为一个ActiveX控件被IE引入. 为避免潜在的混乱JavaScript仅以单线程运行,但XHR的异步特性使得它独立于JS引擎的线程外工作. 数据返回前,其他JS,页面上的交互如常运行,而当数据返回时触发事件. 如今AJAX不单指XHR.所有在不离开当前页面的前提下,由JS主动发起的从服务器端获取JS可解析数据的方案,皆可称AJAX 13 14. 1.6 AJAX--JavaScript与服务器端交互 JavaScript已经具有能力完全的改变所在网页的每个细节. JavaScript的野心不止于此,如果JS能由事件驱动,从服务器端源源不断的获取新鲜数据,那理论上不再需要第二个页面了. 网页上一切来自HTTP,获取数据自然需要JavaScript发起HTTP,接收并理解响应. 于是有了XHR(XmlHttpRequest),首先作为一个ActiveX控件被IE引入. 为避免潜在的混乱JavaScript仅以单线程运行,但XHR的异步特性使得它独立于JS引擎的线程外工作. 数据返回前,其他JS,页面上的交互如常运行,而当数据返回时触发事件. 如今AJAX不单指XHR.所有在不离开当前页面的前提下,由JS主动发起的从服务器端获取JS可解析数据的方案,皆可称AJAX 14 不要使用同步XHR请求,处理好等待状态 使用JSON数据交换 适用一切应用于HTTP请求的优化措施 15. 1.7 Cookie--身份识别与会话保持 再次回到HTTP本身 HTTP是一种没有状态协议 靠存储在客户端的Cookie来标识身份,保持会话 HTTP分Header和Body两部分 HTTP的Header分Request和Response两部分 Request中会带着请求域下的Cookie 服务端可以通过Response种植Cookie Cookie可以种在根域名和所在的子域名下,也可以种植在指定路径下,指定有效时间 JavaScript可以读写所属HTML页面所在域下的Cookie 页面http://item.taobao.com/item.html中的JS可以读写item.taobao.com子域名下和taobao.com根域名下cookie 15 16. 1.7 Cookie--身份识别与会话保持 再次回到HTTP本身 HTTP是一种没有状态协议 靠存储在客户端的Cookie来标识身份,保持会话 HTTP分Header和Body两部分 HTTP的Header分Request和Response两部分 Request中会带着请求域下的Cookie 服务端可以通过Response种植Cookie Cookie可以种在根域名和所在的子域名下,也可以种植在指定路径下,指定有效时间 JavaScript可以读写所属HTML页面所在域下的Cookie 页面http://item.taobao.com/item.html中的JS可以读写item.taobao.com子域名下和taobao.com根域名下cookie 16 静态资源(图片,脚本等)放在不含有cookie的域 最小化cookie大小. HTTP中一个数据包1k,cookie存在于header中,如果过大效率下降很多. 17. 1.8 小结--七种武器 HTTP:一切内容通过HTTP请求获得 HTML:浏览器把HTML解析成Dom树 CSS:定义HTML的显示样式 JavaScript:提供计算能力,处理交互事件 Cookie:网页间,请求间身份识别与会话保持 DHTML:JavaScript操作Dom树(包括CSS) AJAX:JavaScript操纵HTTP(包括Cookie) 所有前端应用托生于这些基础特性的整合 Web2.0主要托生于DHTML和AJAX这类JavaScript的能力扩展 17 18. 1.8 小结--七种武器 HTTP:一切内容通过HTTP请求获得 HTML:浏览器把HTML解析成Dom树 CSS:定义HTML的显示样式 JavaScript:提供计算能力,处理交互事件 Cookie:网页间,请求间身份识别与会话保持 DHTML:JavaScript操作Dom树(包括CSS) AJAX:JavaScript操纵HTTP(包括Cookie) 所有前端应用托生于这些基础特性的整合 Web2.0主要托生于DHTML和AJAX这类JavaScript的能力扩展 18 来提升武器性能吧!Fast By Default! Plan for performance from day 1 ! 23. 3.1 HTTP数据包嗅探 记录HTTP请求的形成瀑布图 -分析HTTP请求间的顺序 -分析单个请求的内容和各阶段时间(域名解析,建立连接,发送请求,等待响应,接收数据) 单机版 HTTPWatch Fiddler Firebug 网络版 基调网络 AliBench 23 24. 3.2 运行时分析(profiling) 记录网页运行时,JS function的运行耗时或CPU内存使用情况: YUI profiler Firebug Profiler Page Speed Activity MS Fast PageTest DynatraceAjax 24 相关工具详细介绍 http://www.phpied.com/performance-tools/ 25. 3.3 浏览器内存结构分析(起步阶段) 检测IE内存泄露工具 IE Leak Detector a.k.a Drip [ http://www.outofhanwell.com/ieleak/ ] 分析浏览器中内存结构和GC情况,这方面的研究刚刚起步,当前技术停留在观察浏览器中内存使用痕迹的水平 IE不开源没有公布相关工具 Mozilla的相关研究项目http://mozillalabs.com/blog/2009/07/browser-memory-tools-directory/ 25 30. 4.1.1 YSlow 35:避免空的Image src Image 带有空字符串作为src的属性值将带来额外的请求,有两种形式: HTML:<imgsrc=""> JavaScript:varimg = new Image();img.src = ""; 这两种形式都有一个同样的效果:浏览器发起另外一个请求到节点所属页面的地址 http://developer.yahoo.com/performance/rules.html#emptysrc 30 32. 4.1.3 BigPipe—combo动态数据 Combo的应用面向多个静态资源的请求合并. 而当一个页面上的动态数据来自多个数据中心时,使用BigPipe技术将动态数据整合在一个HTTP请求中分段输出,达到服务端多数据中心并发,服务端与浏览器端并发的目的. 现有PHP端的并发技术成熟,比如YAHOO的yfed,只要配合提早flush(),发送chunk的HTTP Response给前端即可. BigPipe技术由Facebook引入,适合SNS类应用. http://www.facebook.com/note.php?note_id=389414033919 32 33. 4.1.4 comet - 基于HTTP的服务端push技术 33 服务器端推数据给客户端,保证消息最快速度传递: 使用有一个Ajax异步请求连接在服务端等待 使用一个不关闭连接,不断的flush数据(类似bigpipe). 应用场景:各种WEB IM 和 SNS站点消息通道 当前问题: 浏览器到同一域名连接数有限,影响其他同域请求性能 Web服务器维持长连接消耗过大,存在较严重性能问题 基于 AJAX 的长轮询(long-polling)方式 基于 Iframe及 htmlfile的流(streaming)方式 http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 40. 4.3.1 最小化html 前面的规则要求我们最小化JS和CSS 而html也应该最小化,去掉回车和首尾空格. 但是HTML的压缩存在风险,YAHOO也没有压缩HTML,详见玉伯的说明: http://lifesinger.org/blog/2010/05/why-dont-compress-html/ 特定系统中,风险可以规避或者通过测试排除 40 44. 4.4.2 打开keep-alive 重用HTTP连接 服务打开keep-alive后,连接会保持指定的一段时间才关闭,后续的请求可以重用此连接,节省了HTTP请求中域名解析和建立连接的耗时. 打开keep-alive会给服务端造成额外的压力, 而且连接时串行的,同一连接同一时间只服务一个HTTP请求. 所以要根据实际情况(页面停留时间)调节keep-alive时间. 44 47. 4.5.2 保障网页的可交互性 JavaScript为单线程语言,在运行时页面会处于锁定状态,任何操作没有响应. 所以JS进行大量运算时,要使用相关技术保障页面持续可交互 在所有浏览器中可以实现的方法是,使用setTimeout将大量的循环调用分组执行,每隔一段时间执行一组操作,称Timer. 针对Ajax的XHR请求,绝对不要使用同步模式,否则浏览器会锁住,知道XHR获得到了服务器端返回数据.因为数据返回依赖网络,时间较长,错误可能较大. HTML5规范的 WebWorker为JS提供了多线程机制,线程间使用消息事件联系.异步的XHR也相当于多线程. 47 48. 4.5.3 缩短最快可交互时间(TTI) 最快可交互时间指从浏览器开始访问网页,到网页可以正确处理UI事件交互的时间 受到挑战的是规则把JS放在底部,因为JS放在底部,JS下载和运行依然需要时间. Facebook做法:head加载一个小JS文件,在底部JS加载运行之前,页面事件会请求专门处理这个事件的小段脚本,快速响应 Yahoo首页实践:缩减初始化载入内容,减少底部脚本,加快DomReady,让重点部分可交互.其余部分延迟加载 MS正在研发中的工具Doloto:JS中有大部分在初始化时没有调用,通过自动切分出需要的部分. 48 50. 4.5.5 优化内存使用,防止内存泄露 delete不再需要的对象 移除DomTree中不再需要的节点 移除节点之前先注销节点上绑定的事件 尽量避免JSObject和DomObject的双向引用(特别需要注意IE下隐式的双向引用,如事件注册) 注意XHR也可能引入的内存泄露 http://isaacschlueter.com/2006/10/msie-memory-leaks/ 50 51. 4.5.6 高效JavaScript的一些Tips 访问局部变量的速度最快 优化循环(猜测最易退出处开始)和条件(类似二分法) 大量字符串链接操作优化(老式浏览器用arr.join("")) 使用事件代理 http://www.nczonline.net/blog/2009/06/30/event-delegation-in-javascript/ 优化Dom访问 http://www.phpied.com/dom-access-optimization/ 使用4.5.2节的Timer技术,保持交互流畅 51 52. 4.5.7 第三方代码相关性能问题 第三方代码普遍存在性能问题和隐患.主要是脚本阻滞,HTTP过多等. Steve最近开展了Performance of 3rd Party Content系列调查,评估美国主要的Mashup公司的埋点代码,并给出改进意见. http://www.stevesouders.com/p3pc/ Google对Analytics做了相关优化,Adsence优化进行中参见Velocity2010:Don't Let Third Parties Slow You Down (http://en.oreilly.com/velocity2010/public/schedule/detail/15412 ) 最近在懒懒的广告代码优化相关分享: http://www.slideshare.net/taobaoued/ss-4888423 52 54. 4.6.1内联脚本不要与样式表穿插使用 <link href="1.css"/> <script> ..... </script> <link href="2.css"/> <link href="3.css"/> 建议将内联脚本放在CSS之上. http://www.stevesouders.com/blog/2010/02/15/browser-performance-wishlist/#stylesheet_js 54 57. 4.7.1 进一步讨论提早Flush 57 通常提早Flush</head>之前的内容 其实可以Flush更多次,但是要注意<body>中内容的Flush,只有<body>的直接子节点之后Flush,才能达到提前渲染的目的: <body> <div></div> <----Flush 达到预期 <div></div> </body> <body> <div> <div></div> <----Flush 失败 <div></div> </div> </body> 目标应用:首页搜索框,Search页广告 Facebook BigPipe技术网站速度提升一倍: http://www.facebook.com/notes/facebook-engineering/making-facebook-2x-faster/307069903919 61. 5.1 -- 14条优化军规 1. 尽可能的减少HTTP请求数 2. 使用CDN 3. 添加Expires头(或者 Cache-control) 4. Gzip组件 5. 把CSS样式放在页面的上方。 6. 将脚本放在底部(包括内联的) 7. 避免在CSS中使用Expressions 8. 将javascript和css独立成外部文件 9. 减少DNS查询 10. 压缩JavaScript和CSS文件 (包括内联的) 11. 避免跳转 12. 移除重复的脚本 13. 配置 ETags 14. 缓存Ajax请求 61 62. 5.2 -- 21条最佳实践 25. 减少访问DOM的次数 26. 编写聪明的事件处理器代码 27. 使用 <link> 而不是 @import 28. 避免使用CSS滤镜 29. 优化图片 30. 优化CSS sprites 31. 不要在HTML中缩放图片 32. 减小 favicon.ico 体积并缓存 33. 保证组件不超过25k(mobile) 34. 将组件拆包分到多个文档中(mobile) 35. 避免空的Image src 15. 尽早刷新缓冲区 16. 用 GET 方法发送Ajax请求 17. 组件延迟加载 18. 组件预加载 19. 减少DOM元素个数 20. 多域并行下载 21. 尽量少用iframes 22. 避免 404 错误 23. 减小 cookie 的大小 24. 对某些静态资源减少无谓的cookie传输 62 63. 5.3 – 更多 使用combo合并静态资源 Bigpipe技术合并动态数据 Comet:基于http的服务端推技术 使用DataURI减少图片请求 使用良好的JS,CSS版本管理方案 尝试仅作必要的JS更新 利用本地存储做缓存 关于最小化HTML 进一步讨论Gzip 进一步讨论域名划分 打开keep-alive,重用HTTP连接 使用JSON进行数据交换 保障页面可交互性 缩短最快可交互时间 异步无阻脚本下载 优化内存使用,防止内存泄露 高效的JavaScript 第三方代码性能问题 Inline脚本不要与CSS穿插使用 使用高效的CSS选择器 进一步讨论及早Flush 关于视觉和心理学 63 64. 5.4 WPO 相关资源 书籍: High Performance Web Sites http://book.douban.com/subject/2084131/ Even Faster Web Sites http://book.douban.com/subject/3686503/ High Performance JavaScript http://book.douban.com/subject/4183808/ Website Optimization http://book.douban.com/subject/4124141/ 工具: firebug https://addons.mozilla.org/zh-CN/firefox/addon/1843 yslowhttps://addons.mozilla.org/zh-CN/firefox/addon/5369 pagespeedhttp://code.google.com/intl/zh-CN/speed/page-speed/ firebug&fiddler简明教程: http://www.slideshare.net/taobaoued/ss-3583978 专题: Yahoo: http://developer.yahoo.com/performance/rules.html Google:http://code.google.com/intl/zh-CN/speed/page-speed/docs/rules_intro.html Phpied2009:http://www.phpied.com/performance-advent-calendar-2009/ Velocity2010:http://en.oreilly.com/velocity2010/public/schedule/proceedings 聚合: http://pipes.yahoo.com/pipes/pipe.run?_id=a6cdaf1d9dbe656ba1f0ab714cc3a08e&_render=rss&howmany=10 64