Front-end performance for web designers and front-end developers
notes date: 2013-09-01
source links:
source date: 2013-01-20
The basics
Styles at the top, Scripts at the bottom
- Overall:
- CSS blocks rendering
- JS blocks downloads
- CSS blocks rendering
- Browsers do this so they can render the page progressively (no redraws)
- Javascript blocks downloads
- In general, browsers download as many assets as possible in parallel, but only $n at a time per domain ($n is set by the browser)
- Why?
- JS could change the page and obviate a resource from needing to be downloaded
- Scripts may be needed in a certain order, so the goal is to ensure that dependencies aren’t downloaded and executed out of order
Make fewer requests
Maximizing parallelisation
- Shard the number of domains you serve your static assets from
- If you serve from $d domains and your browser can download $a assets at a time per domain, then your browser can fetch $a * $d assets at a time.
- If these other domains are also maintained by CDNs, then you may also be able to decrease latency on assets served from a more suitable physical location.
HTTP Requests and DNS lookups
- Each time a new domain is referenced, the HTTP request needs to wait for DNS lookup (20-120 msec)
- To decide whether to use additional static asset (sub)domains, balance the duration of downloading all static assets from 1 domain versus the overhead of the DNS lookup
DNS prefetching
- You can instruct the browser to do a pre-fetch DNS records:
<link rel="dns-prefetch" href="http://s0.domain.com">
in your<head>
- This is especially useful for scripts hosted at a 3rd party (tracking widgets such as GA, social media widgets such as Facebook). Since scripts come last, DNS prefetching is likely to have made some good progress by the time the script needs to be fetched.
Resource prefetching
- Fonts and images referenced in CSS are only fetched once the browser hits an HTML element that requires them.
- The dirty way (images only)
- Use a hidden
<div>
that contains the CSS images as<img>
elements with empty alt attributes - Inline
<img>
s are fetched very early, so the download has begun before CSS requires it.
- Use a hidden
- The cleaner way
- Similar to DNS prefetching:
<link rel="prefetch" href="sprite.png">
- There’s disagreement on the web about whether this works as well; some pages say that browsers only do this prefetching when idle, others say that browsers do this kind of prefetching unconditionally
- Similar to DNS prefetching:
CSS and performance
- Because CSS blocks rendering, and DNS lookups block fetching from a new (sub)domain, serve CSS from your primary domain
- CSS is one of performance’s worst enemies
- CSS is fetched before any rendering, even if the CSS is not used on initial pageview (print_view.css) or is only used conditionally (‘media queries’, such as
<link rel="stylesheet" media="screen and (min-device-width: 800px)" href="desktop.css">
) - WebKit is rumored to do it better (necessary CSS is prioritized, and other styles are deferred until after rendering)
- CSS is fetched before any rendering, even if the CSS is not used on initial pageview (print_view.css) or is only used conditionally (‘media queries’, such as
- What to do about CSS
- Never serve from a static/asset domain
- Serve it as early as possible
- Concatenate it to reduce the number of requests
- Gzip and minify it
- Cache it aggressively
GZipping and Minifying
- Minification and gzipping reduced CSS to 7% of its original size
Optimising Images
Spriting
- Load one large image over one request rather than several smaller images over several smaller requests
- Sprites only work on fixed-dimension elements (the workaround to sprite variable-dimension images involves padding them, which then means transmitting useless bits over the wire, which is yucky)
- Some HTML elements can’t be styled to be of fixed-dimension (e.g., an
<li>
). The workaround is to add some empty element within it that is spriteable (such as an<i>
) which can remain empty and carry a background image.
Retina Images
- Retina images, at 2x the resolution in each dimension, are 4x as big.
- They’re also mostly useful on mobile devices, which have less memory, higher latency, and lower bandwidth than non-mobile devices
- Compromises:
- Serve 1.5x size images to all users (this is wasteful for most)
- Use SVGs, since they’re resolution independent, minifiable, and gzippable
Progressive JPGs
- Baseline JPG requires all the bits for a block to have arrived before it renders.
- Progressive JPG shows a whole image sooner, but pixellated, and the image comes into focus as more is loaded.
- Progressive JPGs feel faster