I wonder if there's even value in something like an asm.js-compiled layout system, which absolutely positions elements. One of the insights of React Native is that to build apps, we really only need a small subset of the web's layout algorithms. Only flexbox, really. So if we recognize this subset, and remove everything else, there main thread can focus on really smooth performance.
React Native even performs the flexbox layout on a 3rd thread, and tells the main thread where to absolutely position stuff.
Obviously we want to re-use as much of HTML as we can, but there might be some crazy ways to remove stuff from the main thread.
EDIT: It should be noted that Mercury, a React-inspired library (https://github.com/Raynos/mercury), has examples of running in a web worker. It is pretty cool, but I think it needs to be fleshed out more.
The biggest problems with performance are:
- GC pauses
- triggering reflow
- marshalling data across interfaces (serialization/deserialization of native types into strings and back again).
That last one is an absolute killer when it comes to applying 3D matrix transforms. Basically, you're taking an array of floats, serializing them into a string to do an element.style property assignment, so that the browser can then take that stringified representation and convert it back into an array of floats that it can apply. Huge perf hit here.
People attribute pauses to GC, when it's sometimes just the browser container environment acting up and there's nothing we can do about it - so it's easy to write it off as GC. Not sure about today, but 1.5 years ago (i = new Image(), i.src="http...") could block the JS thread for as much as 19ms. In a larger app, it's easy to write that off as GC, but (at least on iOS) the performance tooling is really lacking and it's tough to find the culprit.
Reflowing is a big deal, I agree.
I'd love to chat more about this with both of you, this seems like a direction definitely worth exploring.
Maybe we could set up a github project for it? Or talk in an issue on your existing repo, nwienert?
Some reading:
https://news.ycombinator.com/item?id=6982485 http://stackoverflow.com/questions/18056922/is-there-a-way-t...
Edit: webpack + webwoker: https://github.com/webpack/webpack/tree/master/examples/web-...
https://github.com/kripken/worker-ui/wiki
Not familiar with webpack, will take a look.
You basically need to change BackendIDOperations and ReactEventListener to send/receive messages vs talking to the real APIs. It's already set up in the codebase to do this (because it actually worked at one time).
Webpack, per usual, already thought of this and has an answer for you :) https://github.com/webpack/worker-loader
Might be worth reading one of the react native devs about why animations might still be hard: http://jlongster.com/First-Impressions-using-React-Native#co...
This idea is also why I hooked up the css-layout project (https://github.com/facebook/css-layout) to a live demo to play around with: http://layout.jlongster.com/
Now of course, I had hand optimized the performance, but my point is that on the web, there was nothing I could do, and with React Native, there was something I could do to make animations smooth. This is not to say you should be doing animations in JS, but if you want highly customizable interactions that can be immediately stopped by a touch processed in JS, you should try it out and see how it feels. For things that are "fire and forget", or platform specific, you should try using CoreAnimation/keyframes etc which protects the animation from your business logic.
What am I missing?
I can't even think of an app that has a parallax effect. If your app is required to have complex animations then web tech is not the right tech choice in general imo
https://github.com/reactjs/react-future/tree/master/05%20-%2...
EDIT: Searching for "Worker" right now didn't bring any mention, but it seems it is a very recent edit (cf https://github.com/gss/gss.github.io/commit/d6a931e3629d4b5d...).
BeOS took UI multithreading farther than any other environment I've ever used. And it paid off: I still think it might be the case that BeOS on circa 2000 hardware was more consistently responsive than any environment I have used before or since.
More technical detail about BeOS's multithreaded UI design: http://arstechnica.com/civis/viewtopic.php?p=17348543&sid=e2...
What, you mean like we do in Servo? https://github.com/servo/servo :-)
Our main thread (if you can call it that) just does compositing and handles dispatching UI events. Script, layout, resource loading, and the rest run concurrently in background threads.
In current browsers, JavaScript runs in the same thread as the UI, right? In Servo, how do you do interaction with the DOM like `clientHeight`? It just pauses the entire JS engine while it goes and talks to the UI thread?
Maybe we should be thinking of all of this in terms that map well to Servo's current architecture.
EDIT: What's really exciting about Servo is that hopefully the architecture's parallelism is really sound, even if certain properties of the current web restrain it. Then we can work on ways to remove those properties, and in Servo it's a simple switch to turn on more and more parallelism.
Yes, but we'd like to experiment with new APIs in the future like `getBoundingClientRectAsync()` that will allow pages to do that kind of thing asynchronously.
By restricting what the programmer can do, it naturally formed a pipeline where layout can be performed in the second stage while JS is determining the next UI update and so on. I'm not sure the extent to which this benefits us right now, but even mobile devices are beginning to have four cores so it seems like a nice property to maintain as long as it doesn't cause problems.
Servo sounds cool, and I'm curious how it takes advantage of a similar architecture but while the programmer has free reign to "clog the pipeline" by synchronous queries on layout etc. I'm sure they've thought of it, I'd just like to hear what they came up with.
There was a lot of hype about hybrid apps "sucking", but I bet it doesn't once you get off the thread.
But running React in a web worker is still a really great idea. There would just be a lot of little edge cases to handle (like when you click a link - you need to prevent default of navigation, then send that link click to the web worker to see if your app wants to prevent default, if not, force the redirect back on the main thread). Having tight control over text editing might be challenging as well. These are difficulties, but I suspect they are a fixed set of challenges that are worth the increased parallelism in an increasingly multicore world.
But are web workers currently The Solution To All Our Mobile App Needs? No, but they're a great tool that are highly underutilized by JS developers, and that React is uniquely positioned to take advantage of.
It's easy to be too aggressive. For example registering a `touchstart` on a DOM node would kill the native behavior and prevent scrolling, even if that's what you wanted. Of course, you could implement scrolling in JavaScript. That's a lot of work and you have to make sure the web worker doesn't block for more than 16ms so that the effect is smooth.
In my experience it's best to use native browser behaviors where possible. You get all sorts of benefits, like scrolling being executed on a separate thread, and don't have to rely on reimplementing everything from the ground up.
Too bad they stopped working on it.
Would be interested to see real examples of where this is makes sense.
Disclosure: we're developing an email client using Cordova and purely web tech using our own framework: https://github.com/techlayer/espresso.js
Serialized data. Workers currently can't have access to canvas contexts.
N2O framework might do that.
Book:
https://synrc.com/apps/n2o/doc/book.pdf
One pattern you can do is send events to the server, server renders data asynchronously (maintains state for each client in a lightweight process), then ships result back to client via websocket binary frames.
You also decide how much rendering happens where. Can even do whole HTML elements on the server if you want.
I've seen Web Workers used in things like graphing libraries, though.
WPF has a UI and a separate closed off rendering thread, which works quite well performance wise.
I think this is actually possible on the web as well. Someone could write a UI framework which runs JS in a Worker, and sends messages to the main thread, on which there is HTML and minimal JS to receive the messages and handle them.
I'm surprised this hasn't been done, or has it and I just haven't heard about it?
If you're worried about the overhead of transferring lots of messages from the Worker to the main thread, I think it can be pretty fast actually. I did an experiment with proxying WebGL that way, which is a fairly high-traffic API, with nice results,
https://blog.mozilla.org/research/2014/07/22/webgl-in-web-wo...
For something rendering a UI, message passing overhead should be reasonable, especially if the framework is smart enough to only send over what changes (like React Native does).