One of the great joys of working at Google is seeing the big trends in web development. It’s genuinely awesome to see all the innovation and excitement around new ways of crafting experiences. Though, if I’m honest, there are other trends I see, too: developers still feel overwhelmed at the vast array of approaches and tooling, struggle with performance, and fight almost daily to create compelling apps & sites that work across devices and browsers.
This post is the first in a series where we look at some of these challenges, and attempt to suggest possible solutions and strategies. So what to begin with? Let’s start with where we are.
It’s 8.30am on a Monday morning. You look out of your car or train window and you see something that looks like this. Rush hour.
The worst time of day to travel. For many it’s not possible to travel at any other time of day because they need to get to work by 9am.
This is exactly what a lot of web code looks like today: everything runs on a single thread, the main thread, and the traffic is bad. In fact, it’s even more extreme than that: there’s one lane from the city center to the outskirts, and quite literally everyone is on the road, even if they don’t need to be at the office by 9am. It really is one of the trends I see, and you don’t normally have to go far to find stats (look at HTTP Archive or one of Alex Russell’s many tweets) that show that there’s more code than ever on the main thread, and that it’s looking to increase over time.
There’s one lane from the city center to the outskirts, and quite literally everyone is on the road, even if they don’t need to be at the office by 9am.
Okay, but what can we do about it? Taking the case of the roads there are a few options, which range in effectiveness and pragmatism:
- Increase capacity. Essentially make more roads.
- Move traffic to other roads. In the UK you can’t ride a bike on a motorway (highway if you prefer) because, well, you’d almost certainly be injured or killed due to the speed at which other traffic is going. The bikes, then, represent traffic that is only allowed to use certain types of road.
- Stagger the traffic. Instead of everyone traveling at 8.30am, if people were able to shift their work days and we could spread traffic out over the course of the day, then theoretically the roads ought to be, on average, quieter.
What would it look like if we applied these three concepts to the web?
Year on year companies ship better phones, that is true. However, it’s also true that the lower bar has actually gone down, such that the gap between entry level and flagship devices has never been wider. In essence, then, relying on increased capacity would be similar to telling someone that they need a supercar to drive on a given road, or, in our case, ‘please upgrade your phone or computer to something “good enough”’. I personally can’t imagine telling someone to do that, especially if what they had was all they could afford, and I don’t think we should ever bank on increased resources to mask capacity issues. True of transport, true of code.
The gap between entry level and flagship devices has never been wider.
Move traffic to other roads
We actually have the option to move non-UI traffic off the main thread today using Workers. React & Preact use virtualized copies of the DOM that don’t technically need to interact directly with the real DOM until late in the update cycle, so this is something that we should look into more.
There are very few notable cases of people making good use of Workers, which is a shame. (I always think of Nolan Lawson’s Pokedex app, which did this awesomely!) True enough, it can be painful to navigate postMessage with Workers, and without doubt most of the abstractions many of us rely on day-to-day are not built with Workers in mind, but if we accept the premise that the main thread is often in a ‘traffic jam’, then by extension we need to seek ways to alleviate the traffic. The Worker is our primitive for doing that.
Unlike the real world, where people work collaboratively in businesses and need to be get to work by 9am (generally speaking), there is rarely a case where code must do the same.
Recently Philip Walton wrote a must-read article on a strategy he called Idle-Until-Urgent, which treats UI work as non-essential by default and only upgrades render priority when certain criteria are met. As I mentioned above, my own personal preference is “it’s on the screen right now”, but even within that single criterion some components are likely to be more important than others; most likely the ones with which the user is interacting. If, for example, they want to compose an email, that’s the most important component bar none.
What does this all point to? For me, I think we need a yet-to-exist scheduler on the web platform itself. Whether you use requestAnimationFrame, setTimeout, setInterval, or requestIdleCallback, you will eventually hit the case where you create something scheduler-like, attempting to orchestrate a queue of discrete tasks. Or you won’t and you’ll run a single, long-running task that just updates everything in one go. And why wouldn’t you? It’s the default we have today. Just like driving on the roads at rush hour.
We need better defaults. We need more organized traffic.
While I have written this article, ideas and thoughts don’t happen in a vacuum. Specifically, in this case, Surma can be thought of as the co-author of this series, since most of it has come from our many conversations together.
But there are others, too, who deserve to be mentioned because they have contributed, either knowingly, or just by saying or doing the right thing at the appropriate time: Doug Fritz, Paul Irish, The Chrome DevTools team, and Nolan Lawson.
There are probably others, too.
Standing on the shoulders of giants here, people.