by Andrew Betts, FT Labs (trib.tv / @triblondon)
We need to care about supporting existing features as much as getting new ones
HTTP requests are painful, so do fewer of them and make them count.
defer
and async
on script tagsSource: Qualcomm
Chrome, MacOS, Velocity Conf wifi | Safari, iOS, T-Mobile EDGE | |
---|---|---|
1s intervals | 180ms | 850ms |
10s intervals | 180ms | 1500ms |
20s intervals | 180ms | 2100ms |
Try it on the JSFiddle.
api.add('getStory', {'path': '/1'}, callback1);
api.add('getStory', {'path': '/1'}, callback2);
api.send(callback3);
api.add('healthcheck', params, callback4);
api.send(callback5);
Live demo (ooo err)
Interested in helping me with this? Look at the code and drop us a line.
Pre-resolve DNS hostnames for assets later in the page:
<link rel='dns-prefetch' href='hostname-to-resolve.com'>
Fetch subresources early so they're already there when needed:
<link rel='subresource' href='/path/to/some/script.js'>
Pre-fetch resources for likely future navgiations:
<link rel='prefetch' href='/most/likely/next/page.html'>
Pre-render an entire page in the background (Chrome only)
<link rel='prerender' href='/overwhelmingly/likely/next/page.html'>
Layout, paints, animation frames and 'jank' coming up.
IE <11, Firefox (current), Safari <7, iOS <7, Android (current), Blackberry <10
IE 11+, Chrome, iOS 7+, Blackberry 10+
Disable hover effects on non-hoverable devices and during scrolls
.hoverable a:hover { ... }
<body class='hoverable'>
...
</body>
Live demo (ooo err)
Activate meter in chrome://flags
No border-radius
Border-radius
The area the browser has to re-layout when you change something
For more info see Wilson Page's post or Boundarizr by Paul Lewis.
var h1 = element1.clientHeight; <== Read (measures the element)
element1.style.height = (h1 * 2) + 'px'; <== Write (invalidates current layout)
var h2 = element2.clientHeight; <== Read (measure again, so must trigger layout)
element2.style.height = (h1 * 2) + 'px'; <== Write (invalidates current layout)
var h3 = element3.clientHeight; <== Read (measure again, so must trigger layout)
element3.style.height = (h3 * 2) + 'px'; <== Write (invalidates current layout)
etc.
var h1 = element1.clientHeight; <== Read
var h2 = element2.clientHeight; <== Read
var h3 = element3.clientHeight; <== Read
element1.style.height = (h1 * 2) + 'px'; <== Write (invalidates current layout)
element2.style.height = (h1 * 2) + 'px'; <== Write (layout already invalidated)
element3.style.height = (h3 * 2) + 'px'; <== Write (layout already invalidated)
h3 = element3.clientHeight <== Read (triggers layout)
etc.
Use Wilson's FastDOM library to get asynchronous DOM today.
fastdom.read(function() {
var h1 = element1.clientHeight;
fastdom.write(function() {
element1.style.height = (h1 * 2) + 'px';
});
});
fastdom.read(function() {
var h2 = element2.clientHeight;
fastdom.write(function() {
element2.style.height = (h1 * 2) + 'px';
});
});
This works by using requestAnimationFrame
to batch writes
Live demo (ooo err)
Image decoding is probably the most expensive
thing you ask the browser to do when your page loads.
data:
URIs
<img src=''>
to trigger decodingYou need the GPU if you're going to animate a
move, scale
filter, rotate
.thing { -webkit-transform: translateZ(0); }
.thing { -webkit-transition: all 3s ease-out; }
.thing.left { -webkit-transform: translate3D(0px,0,0); }
.thing.right { -webkit-transform: translate3D(600px,0,0); }
will-change
.thing { will-change: transform, opacity }
HTML5 can store data on device too, it's just... well, it's complicated.
If you really want to know more, go read this and watch this
ServiceWorker
While we are limited by tiny quotas, we need to learn to live with less.
Text | S | i | m | p | l | e |
---|---|---|---|---|---|---|
Decimal | 83 | 105 | 109 | 112 | 108 | 101 |
As binary | 01010011 | 01101001 | 01101101 | 01110000 | 01101100 | 01100101 |
Shifted | 01010011 01101001 | 01101101 01110000 | 01101100 01100101 |
---|---|---|---|
As hex | 53 69 | 6D 70 | 6C 65 |
UTF-16 | 卩 | 浰 | 汥 |
function compress(s) {
var i, l, out='';
if (s.length % 2 !== 0) s += ' ';
for (i = 0, l = s.length; i < l; i+=2) {
out += String.fromCharCode((s.charCodeAt(i)<<8) + s.charCodeAt(i+1));
}
return out;
}
function decompress_v1(data) {
var i, l, n, m, out = '';
for (i = 0, l = data.length; i < l; i++) {
n = data.charCodeAt(i);
m = Math.floor(n / 256);
out += String.fromCharCode(m) + String.fromCharCode(n % 256);
}
return out;
}
More click, less wait.
Live demo (ooo err)
Note: This demo shows the effect of Fastclick without using Fastclick itself
When you can't make it any faster...
make it seem faster.
For jobs in Beijing, visit www.ftchinese.com/jobs
For jobs in London, visit labs.ft.com/jobs