Radical Statements about the Mobile Web

February 20, 2015

I drafted a long post about the mobile web, but then Flipboard released their new mobile site with a detailed explanation of why they used canvas instead of the DOM to layout content. Subsequent blog posts ensued in response.

Since the topic of 60 FPS mobile apps has already been discussed greatly, my original post isn't relevant anymore (and I don't have time to polish it up). However, I would still like to point out some important issues.

A quick note (I added this after publishing): I have to give huge props to the recently formed Houdini project which is involving all parties of the web to figure out how to make css/layout/rendering extensible. They are talking about all of these problems in depth (see the wiki) and smarter people than me might be able to really solve this.

This was triggered by playing with React Native, but it stems from years of trying to make the web work well on mobile. These statements are intentionally bold to stir discussion. Some of my assertions may be wrong, but I believe there's at least some truth in most of them.

I'm going to try a new point-based format. The interesting thing about it that is it helps make my argument very clear, since all the colorful articulation (which I don't have time to do) is removed. The downside is that it's quite dense, and might be easy to misinterpret. Here we go:

  1. I work for Mozilla, and I want the web to win. However, this is a thought experiment and I'm going to try to take the role of an unbiased observer. Some of the statements are undoubtedly controversial. None of them reflect my employer — these are just my own thoughts.
  2. The web isn't close to competing with higher-end native apps. You may think the UX is getting close, but there's always more jank. Let's not even talk technical; even if it is getting close, when companies want to develop a beautiful, ground-breaking app, they choose native. I've talked to enough developers to see that we aren't close to changing this yet.
  3. Users don't care about the web. You may argue that the web brings all sorts of benefits over native apps, that they have URLs, are accessible, and you can zoom them. Sadly, most users don't care. By now it should be clear that too many users would choose a native app over a web app.
  4. We need to accept this. The longer we downplay the importance of performance of native app animations, the longer we fail. Animations that smoothly respond to gestures are not progressive enhancement on mobile, they are how users interact. Maybe not on very low-end devices, but I think it's wrong to bet the web on the low-end.
  5. The DOM is slow. I don't think you can argue against that. The only question is if it will get faster, which is what everyone seems to assume. "At some point, the DOM will be fast enough and the mobile web will start winning," they say. It's based on nothing. There's no indication the DOM will ever be fast enough, and if it does happen it's lightyears away on mobile. I've seen no technical description of a truly plausible way to make it significantly faster. This is like trying to optimize your rendering loop to render a model with a million polygons, when what you really need to do is reduce the number of polygons in your model.
  6. The DOM makes JavaScript slow. There are land mines in browser JavaScript that kill performance: DOM APIs. All of them are synchronous. If you touch the DOM, the entire JS engine may block for a while. If there's any indication that we are not working on the right solution here, it's that there's no work to make DOM APIs asynchronous, which if the first thing I'd do if we really want to try to make the DOM work. (edit: this statement was too bold. Recently those involved with standards have been looking at other solutions which may actually work out much better.) We need to guarantee that the JS event loop will run at 60 FPS which is impossible right now.
  7. The main thread should only do layout/rendering. Ideally even layout would be on a separate thread. But we need to guarantee that content will be painted at 60 FPS as well, and we can't do anything like image decoding, or especially run JavaScript, on the main thread. The DOM makes it really hard to do this, but asynchronous APIs are a step in the right direction.
  8. JavaScript-based animations are important, which is why all of this matters. You might wonder why off-thread CSS animations aren't working, and it's because there are tons of animations that you can't do with them. It's really hard to do gesture-based (or physics-based) animations with CSS. And besides, when animations are off-thread it introduces delays when trying to interrupt or cancel it.
  9. Maybe we need native support for ScrollViews? Instead of JavaScript-based animations, maybe we need better native support for common gesture-based interactions, like a scroll view that only renders fixed-height items within the view. Or moving an element around based on the finger. This would diminish the need to have custom JS-based solutions, but if you talk to any iOS/Android shop, you'll see how much customization goes into a high-end mobile app. They can "drop-down" into native code and write custom animations, but we can't drop-down like that.
  10. Servo is on the right track. This is the only project that's tackling this correctly. They are writing a parallel browser, where scripting, layout, and everything else run on separate threads. This will expose all the terrible parts of the current web, showing the points at which we stall the JavaScript event loop, or block rendering. This is perfectly summed up by their intention to make asynchronous versions of all the DOM APIs. Finally!
  11. Maybe the DOM is not the answer. The web is not the DOM. If the DOM doesn't work out, we should look for other solutions. At this point, any advanced app has to work against the DOM (see the whole React movement, which Ember is now copying, and others). The industry is crying out for something faster and more controllable than the DOM. Don't be religious about this.
  12. Lower-level APIs are going to be exposed. Work has already started on controlling the layout and measurement systems of browsers, see here. This might finally allow us to start experimenting with custom DOM-like solutions. I believe this is the direction we should be going. The Box Tree API is especially of interest.
  13. Accessibility is important. Once we start circumventing the DOM, we need to think about how to make our content accessible. Nothing shows that this is impossible, and it's obviously important for the web, so don't freak out. This might be way simpler than you think.

Prediction #1: In the next few years, we see a significant amount of effort to run web apps in web workers. Asynchronous APIs are created to interact with anything that runs on the main thread, like layout, storage, etc. reapp.io is doing a lot of interesting research in this vein.

Prediction #2: React Native becomes so popular that a significant portion of web developers use it to write web/native apps. Attempts to mitigate the DOM by running apps in web workers fails to provide the experience of React Native because the DOM is still the bottleneck. By 2018, we see a big push for a collection of lower-level asynchronous APIs to do layout, rendering, and construct accessibility databases instead of using the DOM. Accessibility APIs allow the developer to apply roles to various parts of the layout.

Prediction #3: By 2020, A special mode for shared memory multi-threading becomes available in asm.js, with a fallback to a single-threaded cooperative mode if asm.js isn't specially recognized. This is far-fetched (and not based on any current work), but games are already pushing hard for this. We grant access to the lower-level rendering & layout APIs to a special asm.js subthread, giving developers the ability to construct advanced rendering engines with a dedicated rendering thread. Apps are written in JavaScript inside a web worker, and communicating with the asm.js code is made fast enough.