front end website optimization
DESCRIPTION
Yahoo has developed the de facto standard for building fast front-ends for websites. The bad news: you have to follow 34 rules to get there. The good news: I'll take a subset of those rules, explain them, and show how you can implement those rules in an automated fashion to minimize impact on developers and designers for your high-traffic website.TRANSCRIPT
Optimising The Front-EndUsing YSlow
And PHP(In A Continuous Integration Environment)
Gerard Sychayphp|works 2008 Atlanta, GA, USA
Who am I?
Gerard SychayTechnology Director
Zipscene.comCincinnati, OH, USA
Who am I?
IRL Cool Web 2.0 Avatar
"In sampling the top ten U.S. websites, all but one spend less than 20% of the total response time
getting the HTML document."
- http://developer.yahoo.com/performance/rules.html
Why Optimise Front-End?
Why Optimise Front-End?
•
Why Optimise Front-End?
34 YSlow Rules1. Make fewer HTTP Requests
2. Use a Content Delivery Network
3. Add an Expires or a Cache-Control Header
4. Gzip Components
5. Put Stylesheets at the Top
6. Put Scripts at the Bottom
7. Avoid CSS Expressions
8. Make JavaScript and CSS External
9. Reduce DNS Lookups
10. Minify JavaScript and CSS
11. Avoid Redirects
12. Remove Duplicate Scripts
13. Configure ETags
14. Make Ajax Cacheable
15. Flush the Buffer Early
16. Use GET for Ajax Requests
17. Post-load Components
18. Preload Components
19. Reduce the Number of DOM Elements
20. Split Components Across Domains
21. Minimize the Number of iframes
22. No 404s
23. Reduce Cookie Size
24. Use Cookie-free Domains for Components
25. Minimize DOM Access
26. Develop Smart Event Handlers
27. Choose <link> over @import
28. Avoid Filters
29. Optimize Images
30. Optimize CSS Sprites
31. Don’t Scale Images in HTML
32. Make favicon.ico Small and Cacheable
33. Keep Components under 25K
34. Pack Components into a Multipart Document
34 8 YSlow Rules1. Make fewer HTTP Requests
2. Use a Content Delivery Network
3. Add an Expires or a Cache-Control Header
4. Gzip Components
5. Put Stylesheets at the Top
6. Put Scripts at the Bottom
7. Avoid CSS Expressions
8. Make JavaScript and CSS External
9. Reduce DNS Lookups
10. Minify JavaScript and CSS
11. Avoid Redirects
12. Remove Duplicate Scripts
13. Configure ETags
14. Make Ajax Cacheable
15. Flush the Buffer Early
16. Use GET for Ajax Requests
17. Post-load Components
18. Preload Components
19. Reduce the Number of DOM Elements
20. Split Components Across Domains
21. Minimize the Number of iframes
22. No 404s
23. Reduce Cookie Size
24. Use Cookie-free Domains for Components
25. Minimize DOM Access
26. Develop Smart Event Handlers
27. Choose <link> over @import
28. Avoid Filters
29. Optimize Images
30. Optimize CSS Sprites
31. Don’t Scale Images in HTML
32. Make favicon.ico Small and Cacheable
33. Keep Components under 25K
34. Pack Components into a Multipart Document
Rule 1: Make Fewer HTTP RequestsInstead of:
<script type="text/javascript" src="/javascript/foo.js"></script><script type="text/javascript" src="/javascript/bar.js"></script>
Can we make it:
<script type="text/javascript" src="/javascript/foobar.js"></script>
Instead of:
<link rel=“stylesheet” type=“text/css” href=“/css/foo.css” /><link rel=“stylesheet” type=“text/css” href=“/css/bar.css” />
Can we make it:
<link rel=“stylesheet” type=“text/css” href=“/css/foobar.css” />
What about images?
Rule 3: Add An Expires Header
Rule 3: Add An Expires Header
Rule 3: Add An Expires Header
<Directory "/var/www/html/css"> ExpiresActive On ExpiresByType text/css "access plus 1 year”</Directory>
Rule 3: Add An Expires Header
Rule 3: Add An Expires Header
Rule 3: Add An Expires Header
So what if the file changes?
<link ref=“stylesheet” type=“text/css” href=“main.css” />
<link ref=“stylesheet” type=“text/css” href=“main.css?1207641610” />
<link ref=“stylesheet” type=“text/css” href=“main-1207641610.css” />
Rules 9,20,24: Domains
Rules 9,20,24: Domains
"Avoiding DNS lookups cuts response times, but reducing parallel downloads
may increase response times. [A] guideline is to split these components
across at least two but no more than four hostnames."
Rules 9,20,24: Domains
http://static0.example.com http://static1.example.com ...
BONUS! Optimise subdomains for static contentCookiesHTTP Keep-AliveAllowOverride
Rules 10,29: Minify
Javascript/* Prototype JavaScript framework, version 1.5.1.1 * (c) 2005-2007 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://www.prototypejs.org/ */*--------------------------------------------------------------------------*/var Prototype = { Version: '1.5.1.1', Browser: { IE: !!(window.attachEvent && !window.opera), Opera: !!window.opera, WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 },...
var Prototype={Version:"1.5.1.1",Browser:{IE:!!(window.attachEvent&&!window.opera),Opera:!!window.opera,WebKit:navigator.userAgent.indexOf("AppleWebKit/")>-1,Gecko:navigator.userAgent.indexOf("Gecko")>-1&&navigator.userAgent.indexOf("KHTML")==-1},BrowserFeatures:{XPath:!!document.evaluate,ElementExtensions:!!window.HTMLElement,SpecificElementExtensions:(document.createElement("div").__proto__!==document.createElement("form").__proto__)}...
Rules 10,29: Minify
Javascript
JSMinDojo Shrinksafe, YUI CompressorPacker
Rules 10,29: Minify
CSS
Pretty much just whitespace and comments
Rules 10,29: Minify
Images
jpegtranoptipng
Rule 12: Remove Duplicate Scripts
Can We Do All These At Once?
Let's Find Out...
First Attempt: Template Function
<html> <head> <?php insert_js('/javascript/foo.js', '/javascript/bar.js'); ?> <?php insert_css('/css/foo.css', '/css/bar.css'); ?> </head> <body> <?php insert_img('/images/foo.jpg'); ?> ...
First Attempt: Template Functionfunction insert_js($args){ static $alreadyLoaded = array(); $files = func_get_args(); // get array of javascript files $bundlefile = str_replace('/javascript/', '', join('', $files)); $bundlefile = str_replace('.js', '', $bundlefile); $buffer = ''; $latest = 0; foreach ($files as $file) { if (isset($alreadyLoaded[$file])) continue; else $alreadyLoaded[$file] = true;
$mtime = filemtime(APP_ROOT . $file); if ($mtime > $latest) $latest = $mtime; // get the latest modification time $minified = YuiCompress::compress(APP_ROOT . $file); // minify content $buffer .= "$minified\n"; }
$handle = fopen(APP_ROOT . "/cache/$bundlefile-$latest.js", 'w'); // open bundle fwrite($handle, $buffer); // write minified content to bundle file fclose($handle); $twoBitValue = 0x3 & crc32("$bundlefile.js"); // generate subdomain $path = "http://static{$twoBitValue}.example.com/cache/$bundlefile-$latest.js"; echo "<script type=\"text/javascript\" src=\"$path\"></script>";}
✓Combine✓Expires✓Subdomain✓Minify✓Remove duplicate
First Attempt: Template Function
Instead of:
<script type=“text/javascript” src=“/javascript/foo.js”></script>
<script type=“text/javascript” src=“/javascript/bar.js”></script>
We now have:
<script type=“text/javascript” src=“http://static2.example.com/cache/foobar-1207762384.js”>
</script>
First Attempt: Template Function
Not bad, but… Multiple stat() calls What about CSS (e.g. background-image: url(‘…’))? AND IT MAKES THIS GUY SAD
Second Attempt: Phing
PHP build system similar to make Port of ant to PHP
Second Attempt: PhingCSS
$pattern = ‘/(<link.*href=“[^”]*”.*\/>\s*)+/’;
$buffer = preg_replace_callback($pattern, “insert_css”, $buffer);
Javascript
$pattern = ‘/(<script.*src=“[^”]*”.”></script>s*)+/’;
$buffer = preg_replace_callback($pattern, “insert_js”, $buffer);
Second Attempt: Phing
Images
$pattern = ‘/src=“([^”]*[gif|jpg|png])”’;
$buffer = preg_replace_callback($pattern, “insert_img”, $buffer);
$pattern = ‘/url\(‘?.*[gif|jpg|png]’?\)/”;
$buffer = preg_replace_callback($pattern, “insert_cssimg”,
$buffer);
Beyond Phing: Continuous Integration
Automatic front-end optimisations Automatic unit testing with coverage Automatic syntax checking (with `php -l`) Automatic standards checking (with
PHPCodeSniffer) Automatic deployment to integration Automatic deployment to any environment History of builds
Fin
Summary
Why the front-end is important 34 8 YSlow rules Template functions Continuous deployment
Fin
Links
34 Rules for High Perfomance Websites: http://developer.yahoo.com/performance/rules.html
YSlow homepage: http://developer.yahoo.com/yslow/
Cal Henderson Flickr article: http://www.thinkvitamin.com/features/webapps/serving-javascript-fast
Sitepoint article: http://www.sitepoint.com/article/web-site-optimization-steps/
© 2008. Some rights reserved.