Performance

Performance is the first interaction a user has with the things that we create.

Performance culture

As frontend engineers we need to always be reminding others about performance.

Treat performance as design

Performance isn't just the responsibility of frontend engineering. Like accessibility it's invisible, technical, and the result can slip through the cracks in a project. We should always consider performance as an essential design feature.

Some stats:

  • Google saw a 20% decrease in traffic and ad revenue when page load increased by 0.5s.
  • Amazon see a 1% sales decrease for every 0.1s increase in page load.
  • Users expect 2 seconds. 40% will abandon after 3 seconds.

We surveyed 3000 users about 17 key product drivers. They rated speed 2nd most important only after easy to find content. Patrick Hamann, The Guardian

Set a performance budget

Early on each project should set a maximum page weight, which forces everyone involved in the design process to make some tough, realistic decisions about what deserves to end up on the page. Useful ammunition for saying no. An example performance budget:

  • Time to first byte: 500ms
  • DOM Content Loaded: 2s
  • Page load: 2.5s
  • Page weight: 1MB (before interaction)
  • DNS lookup: 20s
  • HTTP Requests: 40 (before interaction)

Techniques

Reducing HTTP requests

Reducing the number of HTTP requests in your page is the place to start. This is even more important when considering mobile, where DNS lookups over mobile networks often takes longer than downloading the file itself.

  • Combine images into one or more sprites using Compass.
  • Use an icon font instead of multiple images.
  • Inline small images inside CSS using inline-image (no IE7 support).
  • Concatenate CSS and JavaScript into single files (default in Rails).

Third party code

Wherever possible, defer the loading of third party code (e.g. social sharing buttons, video players) until after window.onload. Where this is not possible (e.g. analytics code that needs to be present as soon as possible, use the async attribute on the <script /> element to prevent blocking.

Images

  • Compress images as much as possible. ImageOptim is great.
  • Serve images at the desired size, particularly on small screens.
  • Define which images are critical to the page. Consider lazy-loading images outside of view.

Rendering

Once the page has downloaded, interaction performance is important as well. Anything below 60 frames per second will feel sluggish and poorly built. When dealing with user input, interactions should be less than 100ms to feel instant, and 250ms to feel fast. Some rules of thumb:

  • Load CSS before JavaScript.
  • Don't bind multiple handlers to the resize or scroll events, use throttle/debounce instead.
  • Don't emulate fixed positioning using JavaScript.
  • Animate using CSS3 instead of JavaScript.
  • Avoid Internet Explorer's CSS expression selectors.
  • Keep the number of DOM nodes to a minimum. Consider lazy-loading content.

Exceptions

There are some guidelines that we tend not to follow because of known problems:

Domain sharding

Modern browsers support more parallel downloads than old Internet Explorers. As such, the practice of domain sharding is no longer as beneficial as it once was.

JavaScript at the bottom

Common advice is to load all JavaScript at the bottom of the page, so it doesn't block page rendering. This is sound advice until your page requires JavaScript to render. Having core functionality kick in only after the page has loaded is a usability problem, so we still load all JavaScript in the <head />.

Testing tools