Successfully reported this slideshow.
Your SlideShare is downloading. ×

High Performance Web Pages - 20 new best practices


Check these out next

1 of 76 Ad

More Related Content

Slideshows for you (20)

Viewers also liked (20)


Similar to High Performance Web Pages - 20 new best practices (20)

More from Stoyan Stefanov (20)


Recently uploaded (20)

High Performance Web Pages - 20 new best practices

  1. <ul><li>High Performance </li></ul><ul><li>Web Pages </li></ul><ul><ul><li>Stoyan Stefanov </li></ul></ul><ul><ul><li>Yahoo! Exceptional Performance </li></ul></ul><ul><ul><li> </li></ul></ul><ul><ul><li>PHP Quebec, March 13, 2008 </li></ul></ul>
  2. The sluggish Web <ul><li>We’re getting used to the web as a tool for our day-to-day tasks </li></ul><ul><li>We all want a nice user experience </li></ul><ul><li>We won’t tolerate slow pages (we have options) </li></ul><ul><li>500 ms slower = 20% drop in traffic (Google) </li></ul><ul><li>100 ms slower = 1% drop in sales (Amazon) </li></ul>
  3. This talk <ul><li>How to improve page performance </li></ul><ul><li>Focus on the front-end </li></ul><ul><li>14 best practices for faster pages </li></ul><ul><li>… and 20 more! </li></ul>
  4. Exceptional Performance at Yahoo! <ul><li>Quantify and improve the performance of all Yahoo! products worldwide </li></ul><ul><li>Center of expertise </li></ul><ul><li>Build tools, analyze data </li></ul><ul><li>Gather, research, and evangelize best practices - internally and externally </li></ul>
  6. The Importance of Front-End Performance Back-end= 5% Front-end= 95% Even here, front-end= 88%
  7. Focus on the front-end <ul><li>80-90% of the time </li></ul><ul><li>Easier than the back-end </li></ul><ul><li>Proven to work </li></ul>
  8. List of 14 best practices (updated) <ul><li>Make Fewer HTTP Requests </li></ul><ul><li>Use a Content Delivery Network </li></ul><ul><li>Add Expires header (or Cache-control) </li></ul><ul><li>Gzip Components </li></ul><ul><li>Put CSS at the Top </li></ul><ul><li>Move Scripts to the Bottom (inline too) </li></ul><ul><li>Avoid CSS Expressions </li></ul><ul><li>Make JavaScript and CSS External </li></ul><ul><li>Reduce DNS Lookups </li></ul><ul><li>Minify JavaScript and CSS (inline too) </li></ul><ul><li>Avoid Redirects </li></ul><ul><li>Remove Duplicate Scripts </li></ul><ul><li>Configure ETags </li></ul><ul><li>Make AJAX Cacheable </li></ul> content server server server server javascript javascript javascript javascript content css css css css content content
  9. YSlow <ul><li>Yahoo!’s performance lint tool </li></ul><ul><li>Extension to the Firebug extension to Firefox </li></ul><ul><li>Checks for compliance with the best practices </li></ul><ul><li>Grades (offends) </li></ul>
  11. The Life of Page 2.0 request HTML sent onload page settles conception birth graduation marriage? R.I.P. User perceived “onload” happens somewhere here user interaction, XHRs event handlers, components, XHRs request backend fetching components fetus child teen adult
  12. After YSlow &quot;A&quot;? <ul><li>Flush the buffer early </li></ul><ul><li>Use GET for AJAX requests </li></ul><ul><li>Post-load components </li></ul><ul><li>Preload components </li></ul><ul><li>Reduce the number of DOM elements </li></ul><ul><li>Split components across domains </li></ul><ul><li>Minimize the number of iframes </li></ul><ul><li>No 404s </li></ul><ul><li>Reduce cookie size </li></ul><ul><li>Use cookie-free domains for components </li></ul><ul><li>Minimize DOM access </li></ul><ul><li>Develop smart event handlers </li></ul><ul><li>Choose <link> over @import </li></ul><ul><li>Avoid filters </li></ul><ul><li>Optimize images </li></ul><ul><li>Optimize CSS sprites </li></ul><ul><li>Don't scale images in HTML </li></ul><ul><li>Make favicon.ico small and cacheable </li></ul><ul><li>Keep components under 25K </li></ul><ul><li>Pack components into a multipart document </li></ul>content javascript javascript content content content content server server css css images images images images mobile mobile cookie cookie content
  13. Part I Review of 14 best practices (updated)
  14. Make Fewer HTTP Requests <ul><li>Less components = fast page </li></ul><ul><li>HTTP Request overhead </li></ul><ul><li>Combine scripts, combine stylesheets, combine images into CSS sprites </li></ul>
  15. CSS Sprites background-position: -0px -0px; background-position: -20px -0px; background-position: -40px -0px; background-position: -60px -0px; background-position: -80px -0px; background-position: -100px -0px; background-position: -120px -0px; background-position: -140px -0px; background-position: -160px -0px; background-position: -180px -0px; One request instead of ten! Tools:
  16. Use a Content Delivery Network <ul><li>For static components </li></ul><ul><li>Content closer to your users </li></ul><ul><li>Akamai, Amazon S3 </li></ul>
  17. Add Expires header (or Cache-control) <ul><li>For static components </li></ul><ul><ul><li>“ Never expire” policy, far future Expires header </li></ul></ul><ul><ul><li>Once a component is served, the browser never asks for it again </li></ul></ul><ul><ul><li>When you need to change a component, rename it </li></ul></ul><ul><ul><li>Apache example: </li></ul></ul><ul><ul><li>ExpiresActive On ExpiresDefault &quot;modification plus 10 years&quot; </li></ul></ul><ul><li>For dynamic components </li></ul><ul><ul><li>Use Cache-control </li></ul></ul><ul><ul><li>Help the browser send If-Modified-Since </li></ul></ul><ul><ul><li>Writeup on YUI blog/YDN coming up, stay tuned </li></ul></ul>
  18. Gzip Components <ul><li>You send zipped content over the wire, the browser unpacks it </li></ul><ul><li>Modern browsers understand compressed content </li></ul><ul><li>Search engine spiders do too </li></ul><ul><li>Request header </li></ul><ul><li> Accept-Encoding: gzip,deflate </li></ul><ul><li>Response header </li></ul><ul><li> Content-Encoding: gzip </li></ul><ul><li>All text components should be sent gzipped: html (php), js, css, xml, txt… </li></ul>
  19. Put CSS at the Top <ul><li>Firefox and IE will not render anything before the last piece of CSS arrives over the wire </li></ul><ul><li>Even CSS that is not needed such as @media print </li></ul><ul><li>Place the stylesheets as early as possible in the document </li></ul><ul><li><head> </li></ul><ul><li><title>My page</title> </li></ul><ul><li><link href=“styles.css” …/> </li></ul><ul><li></head> </li></ul><ul><li><body> </li></ul><ul><li><!-- content --> </li></ul>
  20. Move Scripts to the Bottom (inline too) <ul><li>Scripts block downloads </li></ul><ul><li>The browser’s logic: since this script can do location.href or document.write at any time, why download possibly useless components </li></ul><ul><li>Move scripts to the bottom to remove the download block </li></ul><ul><li>Inline scripts too </li></ul><ul><li><!-- content --> </li></ul><ul><li><script src=“script.js” …/> </li></ul><ul><li></body> </li></ul><ul><li></html> </li></ul>
  21. Avoid CSS Expressions <ul><li>CSS expression: </li></ul><ul><li>#content { </li></ul><ul><li>position: absolute; </li></ul><ul><li>left: expression(document.body.offsetWidth+‘px’); </li></ul><ul><li>} </li></ul><ul><li>IE-only way to have JavaScript in CSS </li></ul><ul><li>They tend to get executed more often than you planned, think onmousemove often </li></ul><ul><li>Smart expressions overwrite themselves </li></ul>
  22. Make JavaScript and CSS External <ul><li>Helps with caching, “never expire” policy </li></ul><ul><li>Share with other pages </li></ul><ul><li>But this is two more HTTP requests </li></ul><ul><li>Homepages might consider inlining </li></ul><ul><li> </li></ul>
  23. Reduce DNS Lookups <ul><li>Browser needs to map domain name to an IP address </li></ul><ul><li>DNS lookups take time </li></ul><ul><li>2-4 domains per page </li></ul>
  24. Minify JavaScript and CSS (inline too) <ul><li>Minify, but still gzip </li></ul><ul><li>JSMin (written in JavaScript, but has a PHP port) </li></ul><ul><li>YUI compressor – minifies CSS too </li></ul><ul><li>Inline styles and scripts should also be minified </li></ul>
  25. Minify: before <ul><li>/** </li></ul><ul><li>* The dom module provides helper methods for </li></ul><ul><li>* manipulating Dom elements. </li></ul><ul><li>* @module dom </li></ul><ul><li>* </li></ul><ul><li>*/ </li></ul><ul><li>(function() { </li></ul><ul><li>var Y = YAHOO.util, // internal shorthand </li></ul><ul><li>getStyle, // for load time browser branching </li></ul><ul><li>setStyle, // ditto </li></ul><ul><li>propertyCache = {}, // for faster hyphen converts </li></ul><ul><li>reClassNameCache = {}, // cache regexes for className </li></ul><ul><li>document = window.document; // cache for faster lookups </li></ul><ul><li>YAHOO.env._id_counter = YAHOO.env._id_counter || 0; </li></ul>
  26. Minify: after (function(){var B=YAHOO.util,K,I,J={},F={},M=window.document;YAHOO.env._id_counter=YAHOO.env._id_counter||0;
  27. Avoid Redirects <ul><li>A wasted HTTP request </li></ul><ul><li>Causes a restart </li></ul>
  28. Remove Duplicate Scripts <ul><li>Duh! </li></ul><ul><li>IE might decide to download them again </li></ul>
  29. Configure ETags <ul><li>ETags are meant to help with caching </li></ul><ul><li>A component served from server A has a different ETag than the same component served from B </li></ul><ul><li>Configure ETags not to include inode </li></ul><ul><li>… or just remove them and implement “never expire” policy </li></ul><ul><li>Apache default FileETag INode MTime Size </li></ul><ul><li>Change to FileETag None </li></ul>
  30. Make AJAX Cacheable <ul><li>Content returned from XMLHttpRequest s is like any other component </li></ul><ul><li>Should be gzipped </li></ul><ul><li>Could be cached </li></ul><ul><li>Cache-control: max-age=? </li></ul>
  31. Part II After YSlow “A”: 20 more best practices
  32. Part II tag: server tag: content tag: cookie tag: javascript tag: css tag: images tag: mobile
  33. Flush the buffer early <ul><li>Let the browser start fetching components while your backend is busy </li></ul><ul><li>PHP has the function flush() </li></ul><ul><li>Best for busy backends / light frontends </li></ul><ul><li>... <!-- css, js --> </li></ul><ul><li></head> </li></ul><ul><li><?php flush(); ?> </li></ul><ul><li><body> </li></ul><ul><li>... <!-- content --> </li></ul><ul><li>Case Study: Yahoo! Search </li></ul>
  34. Use GET for AJAX requests <ul><li>GET is for retrieving data </li></ul><ul><li>POST is a two-step process (send headers, send data) </li></ul><ul><li>GET request is one TCP packet (unless you have a lot of cookies) </li></ul><ul><li>Max URL length 2K (because of IE) </li></ul><ul><li>POST without actually posting data is like GET </li></ul><ul><li>Yahoo! Mail Research </li></ul>
  35. Part II tag: server tag: content tag: cookie tag: javascript tag: css tag: images tag: mobile
  36. Post-load components <ul><li>Ask yourself: what's absolutely required in order to render the page initially? </li></ul><ul><li>The rest can wait (drag and drop, animations, hidden content, images below the fold) </li></ul><ul><li>JavaScript is ideal candidate for splitting </li></ul><ul><li>YUI Image Loader </li></ul><ul><li>YUI Get Utility </li></ul>
  37. Post-load components <ul><li>Case study: </li></ul><ul><li>onload.js and onload.css </li></ul><ul><li>Progressive enhancement </li></ul>
  38. Preload components <ul><li>Preload </li></ul><ul><li>Items you'll need in the future </li></ul><ul><li>Unconditional preload ( loads a sprite onload) </li></ul><ul><li>Conditional preload ( after you type in the input box) </li></ul><ul><li>Anticipated preload – preload in advance before launching a redesign </li></ul>
  39. Preload components (contd.) <ul><li>Unconditional preload example </li></ul>
  40. Preload components (contd.) <ul><li>Conditional preload example – </li></ul><ul><li>When you start typing the page can safely assume you’ll hit the search results page </li></ul><ul><li>Time to preload </li></ul>
  41. Reduce the number of DOM elements <ul><li>World's fastest page? about:blank ! </li></ul><ul><li>A complex page means more bytes to download </li></ul><ul><li>It also means slower DOM access in JavaScript </li></ul><ul><li>It also may mean using semantically incorrect markup (like nested tables or abusing <div> s) </li></ul><ul><li>Use semantic markup </li></ul><ul><li>Use YUI's reset.css, fonts.css, grids.css </li></ul><ul><li>Easy to test, just type in Firebug’s console: </li></ul><ul><li>document.getElementsByTagName('*').length </li></ul><ul><li> is a busy page and still under 700 elements (HTML tags) </li></ul>
  42. Split components across domains <ul><li>Maximize parallel downloads </li></ul><ul><li>But not more than 2-4 domains, because of the DNS lookup penalty </li></ul><ul><li> – HTML content </li></ul><ul><li> – Static components </li></ul><ul><li>Future: IE8 will allow 6 requests per domain </li></ul>
  43. Split components (contd.) 2 components in parallel 8 components in parallel
  44. Minimize the number of iframes <ul><li><iframe> pros: </li></ul><ul><ul><li>Can help with slow third-party content like badges and ads </li></ul></ul><ul><ul><li>Security sandbox </li></ul></ul><ul><ul><li>You can download scripts in parallel </li></ul></ul><ul><li><iframe> cons: </li></ul><ul><ul><li>They have a cost even if blank </li></ul></ul><ul><ul><li>They block page onload </li></ul></ul><ul><ul><li>Non-semantic </li></ul></ul>
  45. No 404s <ul><li>404 Not Found </li></ul><ul><li>Useless downloads </li></ul><ul><li>Some sites have helpful 404s “Did you mean X?”… </li></ul><ul><li>… which uses server resources (DB, etc) </li></ul><ul><li>When an external JavaScript is a 404, the browser will still try to parse it and find something usable in it </li></ul>
  46. No 404s (contd.) The second component is a 404 JavaScript and it blocks the rest of the page
  47. Part II tag: server tag: content tag: cookie tag: javascript tag: css tag: images tag: mobile
  48. Reduce cookie size <ul><li>Eliminate unnecessary cookies </li></ul><ul><li>Keep cookie sizes as low as possible to minimize the impact on the user response time </li></ul><ul><li>Be mindful of setting cookies at the appropriate domain level so other sub-domains are not affected </li></ul><ul><li>Set an Expires date appropriately. An earlier Expires date or none removes the cookie sooner, improving the user response time </li></ul>
  49. Cookie-free hosting for components <ul><li>Option 1: Separate subdomain ( </li></ul><ul><li>Option 2: A new TLD (e.g.,, </li></ul><ul><li>Proxies might refuse to cache </li></ul><ul><li> vs </li></ul><ul><li>no-www leaves you no choice but to write cookies to * </li></ul>
  50. Part II tag: server tag: content tag: cookie tag: javascript tag: css tag: images tag: mobile
  51. Minimize DOM access <ul><li>DOM access is the slowest </li></ul><ul><li>Cache </li></ul><ul><li>Update nodes “offline” and then add them to the tree </li></ul><ul><li>Avoid fixing layout with JavaScript </li></ul>
  52. Develop smart event handlers <ul><li>Don't wait for onload , use DOMContentLoaded </li></ul><ul><li>Events bubble up, so use delegation (attach listeners to outer elements) </li></ul><ul><li>Clean up to prevent IE memory leaks </li></ul><ul><li>Careful with onresize </li></ul><ul><li>Use YUI Event utility </li></ul>
  53. Part II tag: server tag: content tag: cookie tag: javascript tag: css tag: images tag: mobile
  54. Choose <link> over @import <ul><li>CSS should be at the top </li></ul><ul><li>In IE @import is the same as putting <link> at the bottom </li></ul>
  55. Avoid filters <ul><li>IE proprietary </li></ul><ul><li>AlphaImageLoader </li></ul><ul><li>Fixes an IE6 problem with semi-transparent PNGs, IE7 is fine </li></ul><ul><li>Blocks rendering, freezes the browser </li></ul><ul><li>Increased memory consumption </li></ul><ul><li>Per element, not per image! </li></ul><ul><li>Best: Avoid completely, use gracefully degrading PNG8 </li></ul><ul><li>Fallback: use underscore hack _filter not to penalize IE7+ users </li></ul>
  56. Part II tag: server tag: content tag: cookie tag: javascript tag: css tag: images tag: mobile
  57. Optimize images <ul><li>GIF - don't use a bigger palette than you need </li></ul><ul><li>Use PNGs instead of GIFs </li></ul><ul><li>“ All we are saying is: Give PiNG a Chance!&quot; </li></ul><ul><li>pngcrush tool (or optipng, or pngoptimizer) </li></ul><ul><li>Removing gamma chunks also helps with cross-browser colors </li></ul><ul><li>Strip comments </li></ul><ul><li>jpegtran - lossless JPEG operations, can be used to optimize and remove comments </li></ul>
  58. Optimize images (contd.) <ul><li>You can write a simple tool that walks your image directories before site launch and does the following: </li></ul><ul><ul><li>Convert all GIFs to PNGs (and check if there’s a saving) > convert image.gif image.png </li></ul></ul><ul><ul><li>Crush all PNGs > pngcrush image.png –rem alla –reduce result.png </li></ul></ul><ul><ul><li>Strip comments from JPEGs > jpegtran -copy none -optimize -perfect src.jpg dest.jpg </li></ul></ul>
  59. Optimize images (contd.) <ul><li>You’d be surprised how many sites, from small to huge, could optimize the download size </li></ul><ul><li>200K of useless image information sent over the wire for a single page?! </li></ul>
  60. Optimize CSS sprites <ul><li>Choose horizontal over vertical when possible </li></ul><ul><li>Combine similar colors </li></ul><ul><li>Keep color count low (<256) to fit in a PNG8 </li></ul><ul><li>“ Be mobile-friendly” – don’t leave big gaps </li></ul><ul><ul><li>Filesize doesn’t increase much, but the image needs to be decompressed into a pixel map </li></ul></ul><ul><ul><li>100x100 is 10000 pixels </li></ul></ul><ul><ul><li>1000x1000 is 1 Million pixels </li></ul></ul><ul><ul><li>Case study: Yahoo! Mail Classic </li></ul></ul>
  61. Optimize sprites
  62. Don't scale images in HTML <ul><li>Downloads unnecessary bytes </li></ul><ul><li>If you need </li></ul><ul><li><img width=&quot;100&quot; height=&quot;100&quot; src=&quot;mycat.jpg&quot; /> </li></ul><ul><li>then have mycat.jpg 100x100 not 500x500 </li></ul>
  63. Make favicon.ico small and cacheable <ul><li> </li></ul><ul><li>Necessary evil: </li></ul><ul><ul><li>The browser will request it </li></ul></ul><ul><ul><li>Better not respond with a 404 </li></ul></ul><ul><ul><li>Cookies are sent </li></ul></ul><ul><ul><li>Cannot be on CDN </li></ul></ul><ul><ul><li>Interferes with the download sequence </li></ul></ul><ul><li>Make it small (<= 1K) </li></ul><ul><li>Animated favicons are not cool </li></ul><ul><li>Set Expires header </li></ul><ul><li>Tools: imagemagick, png2ico </li></ul><ul><li>Case study: Yahoo! Search - favicon.ico is 9% of all page views! </li></ul>
  64. Bonus: crossdomain.xml <ul><li>Cross domain policy for Flash/Flex </li></ul><ul><li>Sits in the root: </li></ul><ul><li><cross-domain-policy> </li></ul><ul><li><allow-access-from domain=&quot;*; secure=&quot;false&quot;/> </li></ul><ul><li></cross-domain-policy> </li></ul><ul><li>Set Expires header </li></ul><ul><li>gzip </li></ul><ul><li>… and secure while at it, don’t do: </li></ul><ul><li><allow-access-from domain=&quot;*“ /> </li></ul>
  65. Part II tag: server tag: content tag: cookie tag: javascript tag: css tag: images tag: mobile
  66. Keep components under 25K <ul><li>Because iPhone won’t cache them </li></ul><ul><li>Uncompressed size under 25Kb </li></ul><ul><li>Minify HTML in addition to JS and CSS </li></ul>
  67. Pack components into a multipart document <ul><li>For UAs that support it (iPhone doesn’t) </li></ul><ul><li>Like an email with attachments </li></ul>
  68. Part II tag: server tag: content tag: cookie tag: javascript tag: css tag: images tag: mobile
  69. Tools <ul><li>YSlow ( http:// / ) </li></ul><ul><li>Fiddler ( http:// /fiddler/ ) </li></ul><ul><li>IBM Page Detailer ( http:// ) </li></ul><ul><li>HTTPWatch ( http:// / ) </li></ul><ul><li>AOL Pagetest ( http:// / ) </li></ul><ul><li>Firebug Net Panel ( http:// / ) </li></ul>
  70. IBM Page Detailer <ul><li>Methodology </li></ul><ul><ul><li>Packet Sniffer </li></ul></ul><ul><li>Competitive Advantage </li></ul><ul><ul><li>Most accurate </li></ul></ul><ul><ul><li>Provides detailed data </li></ul></ul><ul><ul><li>Works for any browser </li></ul></ul><ul><ul><li>Best waterfall view </li></ul></ul><ul><li>Drawbacks </li></ul><ul><ul><li>Requires a download </li></ul></ul><ul><ul><li>90 day free trial </li></ul></ul><ul><ul><li>Runs only on Windows </li></ul></ul><ul><ul><li>Misses cached components </li></ul></ul>
  71. Firebug NET Panel <ul><li>Methodology </li></ul><ul><ul><li>Packet Sniffer </li></ul></ul><ul><li>Competitive Advantage </li></ul><ul><ul><li>Integrated with Firebug </li></ul></ul><ul><ul><li>Displays waterfall view </li></ul></ul><ul><ul><li>Provides HTTP header info </li></ul></ul><ul><li>Drawbacks </li></ul><ul><ul><li>Runs only in Firefox </li></ul></ul><ul><ul><li>Inaccurate waterfall view </li></ul></ul><ul><ul><ul><li>No render time </li></ul></ul></ul><ul><ul><ul><li>No parse time </li></ul></ul></ul><ul><ul><ul><li>No redirects </li></ul></ul></ul><ul><ul><ul><li>No DNS lookups </li></ul></ul></ul><ul><ul><li>Misses cached components </li></ul></ul>
  72. URLs – Exceptional Performance <ul><li>YUI blog </li></ul><ul><li> </li></ul><ul><li>YDN (Yahoo Developer Network) </li></ul><ul><li> </li></ul><ul><li>YDN blog </li></ul><ul><li> </li></ul><ul><li>Mailing list (Yahoo! Group) </li></ul><ul><li> </li></ul><ul><li>Feedback </li></ul><ul><li> </li></ul>
  73. URLs (contd.) <ul><li>&quot;When the Cookie Crumbles&quot; Tenni Theurer, Steve Souders </li></ul><ul><li> </li></ul><ul><li>&quot;Maximizing Parallel Downloads in the Carpool Lane&quot;, Tenni Theurer, Patty Chi </li></ul><ul><li> </li></ul><ul><li>YUI Image Loader ( http:// / ) </li></ul><ul><li>YUI Get ( ) </li></ul><ul><li>YUI Compressor ( http:// / contains a Java port of an internal PHP CSS minifier tool written by Isaac Schlueter, ) </li></ul><ul><li>JSMin ( http:// ) </li></ul><ul><li>&quot;High-performance AJAX applications&quot; Julien Lecompte </li></ul><ul><li>Yahoo! engineer Michael J. Radwin talk back in 2004 </li></ul><ul><li>http:// / </li></ul>
  74. Credits – thank you!
  75. Take-home <ul><li>Focus on the front-end </li></ul><ul><li>Harvest the low hanging fruit </li></ul><ul><li>Be an advocate for your users </li></ul><ul><li>Start early </li></ul>
  76. Thank you! Merci beaucoup!

Editor's Notes