Archive for February 3, 2009

Web Site Speed – Best Practices for Achieving Good YSlow Scores

Make Fewer HTTP Requests

  • 40-60% of daily visitors come with an empty cache – the key to making these first-time visitors happy is less HTTP requests
    • CSS sprites
    • Combined files (combine all scripts into a single file, same for CSS)
    • Inline images (not yet supported in all major browsers)

Gzip Components

  • Reduces page weight and accelerates user experience
  • Worthwhile to zip:
    • HTML docs
    • Scripts
    • Stylesheets
    • XML docs
    • JSON docs
  • Not worthwhile zipping (are already compressed – waste of CPU time and may actually increase file size)
    • Images
    • PDF files

Put Stylesheets at the Top, Scripts at the bottom

  • Allows for page to load progressively (display content as soon as possible instead of waiting until all data has arrived to display everything at once)
  • Scripts block parallel downloads – browser won’t begin another downloads (even on different hostnames) while a script is downloading
  • Minimize use of “document.write” (or equivalents to this functionality) ontil the bottom of the page
    • Use the DEFER attribute where possible, which indicates that the script does not contain a “document.write” line and the browser can continue rendering (firefox doesn’t support this)

Avoid CSS Expressions

  • Although powerful, these are evaluated more often than one would expect – they are evaluated when:
    • page is rendered
    • page is resized
    • page is scrolled
    • user moves the mouse over the page
  • Yahoo’s developers found (using counters in these expressions) that mobing the mouse around the page can easily generate more than 10,000 evaluations

Make JavaScript and CSS External

  • external CSS and JavaScript files are cached; JavaScript and CSS that are inlined in the HTML documents get downloaded every time the HTML document is requested.

Reduce DNS Lookups

  • Reducing the number of unique hostnames has the potential to reduce the amount of parallel downloading that takes place in the pagehowever;

    reducing parallel downloads may increase the response times

  • A balance must be struck between the number of unique hostnames and the amount of parallel downloading potential of each page – Yahoo recommends to split these components across at least 2, but no more than 4 hostnames; this generally results in a good compromise between reducing DNS lookups and allowing a high degree of parallel downloads.

Minify JavaScript and CSS

  • Minifying code is simply removing unnecessary whitespace and commenting to reduce file size.
  • 3rd party automated minifying tools exist such as JSMin

Make favicon.ico Small and Cacheable

  • “favicon.ico” – an image that stays on the root of your server
  • Even if you don’t care about it, the browser will still request it
  • it is better to not respond to this request with a 404 Not Found, and cookies are sent every time its requested (which will be every page if you are responding with 404 Not Found
  • To mitigate these problems:
    • Make sure it is small (< 1K)
    • If you don’t care about setting this to anything, give it a long expiry time

Minimize the Number of iframes

  • Pros of using iframes:
    • Helps with slow third-party content (ads, external pictures, etc.)
    • Can be used as a security sandbox
    • Allows for scripts to be downloaded in parallel
  • Cons of using iframes:
    • Costly, even if left blank
    • they block page onload
    • Non-semantic

Appropriately Preload/Post-load Components

  • Preload only what is absolutely necessary for the page to render
  • JavaScript libraries that do things like drag and drop animations can to be post-loaded

Optimize use of Ajax

  • Make Ajax Cacheable
  • Use GET for AJAX Requests
  • All rules and guidelines also apply to Ajax
    • Gzip Components
    • Reduce DNS Lookups
    • Minify JavaScript
    • Avoid 301s, 302s, and 404s
    • etc.

Other optimizations:

  • Avoid 301s, 302s, and 404s whenever possible
  • Don’t Scale Images in HTML (costs time to scale images – make the picture files themselves appropriately sized)
  • Keep Components under 25K
  • Remove Duplicate Scripts
  • Investigate whether or not ETags are a good idea for your website
  • Flush the Buffer Early
    • Ideally right between the end of the head tag and before the body tag
    • Yahoo pioneered research and real user testing to prove the benefits of using this technique (More Info)
  • Use a Content Delivery Network
    • Yahoo moved their static content from their web servers to a 3rd party CDN company and saw a 20% increase in user response times.
  • Add an Expires or a Cache-Control Header
    • Refers to an equivalent to our “Strong” and “Weak” cache policies, which we already implement heavily
  • Reduce DOM access and the number of DOM elements
    • Easy way to get the count of DOM objects on a page: in Firebug’s console, typedocument.getElementsByTagName('*').length
  • Reduce Cookie Size
  • Choose <link> over @import (Allows for progressive rendering)
  • Avoid Filters (such as the IE-proprietary AlphaImageLoader
    • blocks rendering and freezes browser while the image is being downloaded
    • Applied per element, rather than per image, which only multiplies the above-mentioned problem
  • Develop Smart Event Handlers
  • Split Components Across Domains where possible
  • Pack Components into a Multipart Document – allows you to fetch several components with one HTTP request (iPhone does not support this)

By: Brett McClelland

Leave a comment »

Creating Fixtures from Within Tests

Django gives you a ‘dumpdata’ target which will create a fixture from all the records in your schema. For what we wanted, this was overkill. We had an existing unit test which was creating data in one test, and it was just the right amount of data for what we wanted. After searching through the Django codebase, it became clear that we could pass the objects we had in that test straight to the JSON serializer, and write the output to file. This ended up looking something like this:-

from django.core.serializers import json
serializer = json.Serializer()
objectsToSerialize =
MyModel.objects.filter(column='restriction')
with open('my_fixture.json','w') as f:
. f.write(serializer.serialize(objectsToSerialize, indent=4))

And that’s it! You can also spin up a shell, using:-

python manage.py shell

and load the data you want to create fixtures from if you don’t have any tests that create the data you want already.

By: Chris Tarttelin

Leave a comment »