The future of JavaScript MVC frameworks
- Transfer
Introducing Om

We, in our ClojureScript corner, have known this for a long time - all our data structures are immutable and are based on original collections from Clojure written in Java. Modern JavaScript engines are currently quite optimized and we often observe the performance of these collections within 0.4X of the JVM.
Stop, stop, stop. But what does the performance of immutable data structures have to do with JavaScript MVC? - Essential enough.
It may not be very easy to explain, but still I will try. The fact is that the immutable data structures presented in the new Om library allow you to create applications much faster than on popular JS MVC frameworks, such as MVC Backbone.js (without manual optimization). Om is built on Facebook’s great framework, React . If you have not heard about it before, I recommend watching a video from JSConf EU 2013. An interesting fact is that, due to immutable collections, Om can show better results than when using React without any modifications.
The benchmarks presented below were not created to prove that Om is the fastest library in the world for building UI. They were created to demonstrate that very often decisions are made that cannot be globally optimized. Also, modern frameworks often provide a small amount of documentation and assistance, in connection with which users make decisions that lead to performance problems.
Of course, problems in applications can be tedious to solve one after another. But you can use frameworks like Om that provide complex levels of component abstraction. This will help get rid of a number of simple and time-consuming manual optimization methods.
Benchmark game
Open Om TodoMVC in a browser and launch the first benchmark. It creates 200 list items, and on an 11-inch Macbook Air in Safari 7, it runs in 120ms.
Now open Backbone.js TodoMVC and run a similar benchmark. On my machine, the page rendered in about 500ms.
In Chrome and Firefox, on my machine, Om shows results about 2-4 times faster than Backbone.js.
If you try to switch all the list items, Om will do it instantly, while with a similar action, Backbone.js will show a slight hang.
This difference is likely due to Om redrawing the page during the requestAnimationFrame event. This allows you to significantly optimize your application.
Let's take a look at the profiler in Chrome Dev Tools for these benchmarks. We can see a big difference in the work of React / Om out of the box compared to the non-optimized Backbone.js:
React / Om:

Backbone.js:

In my opinion, the React / Om graph shows that there are much more opportunities for global optimizations and improvements .
Ok, great work! But still ... Only the fact of productivity increase in 3 main browsers by 2-4 times should have been of interest to many. Especially considering that we are reaching this level thanks to immutable data structures. There is no 30-40 times increase that I made on Twitter.
Now try the second Om benchmark - it creates 200 elements, switches them all 5 times, and then removes them. In Safari 7 on my MacBook, it all happens in about 5ms.
Next, run Backbone.js. Be sure to remove all items first, and then try the second benchmark. On my machine, in the Safari browser, it ran for 4200ms.
How is this possible? - Simply.
Om almost never does unnecessary work. The data, views, and controller logic are not interconnected. When changing data, we will never immediately render the page. We simply defer redrawing changes until the requestAnimationFrame event. Essentially, Om works with the browser as a GPU.
I assume that many JS MVC applications follow the architecture of Backbone.js TodoMVC applications, linking together model and view changes, as well as other independent parts, such as serializing the application state in LocalStorage. Only a few frameworks provide the necessary support to properly build the architecture of their applications. In fact, this state of affairs is not surprising, since most of the frameworks are based on string templates, CSS selectors and direct manipulation of the DOM. Om leaves behind all the signs of a place-oriented programming style and other potential performance vulnerabilities.
You can of course use Backbone.js or your favorite JS MVC framework with React, and it's a good combination providinggreat benefit . However, I do not believe in event-oriented MVC systems. And the benchmarks above confirm this. Separating models and views is just the first important step.
Hopefully this will give some thought to fans of the current JS MVC frameworks, and even people who believe in using only native JavaScript and jQuery. Above, I tried to show that a JavaScript compiled language that uses slower data structures is ultimately faster than its competitor to build more complex interfaces. At the top of the list of best results is Om TodoMVCwith the same functionality as all the other frameworks, ~ 260 lines of code (including all template ones) and a reduced weight of 63K gzipped (this all includes: React - 27K, the standard ClojureScript library, core.async, routing library, and several helpers from Google Closure).
If you are a JavaScript developer, I think you should take a good look at React. I think in the future the React connection with a library that provides the use of persistent data structures like mori, can lead JavaScript applications to the flexible and highly customizable architecture that Om provides. Despite the fact that immutable data structures generate more garbage, we still hope that modern developers will cope with this problem. Also, the performance of the devices we carry in our pockets is constantly improving.
Technical description follows.
How it works
Changes and queries to the DOM tree are a big vulnerability for performance, and React uses an approach that bypasses these places sacrificing expressiveness. It provides a well-designed object-oriented interface, but if you look under the hood, we will see the sources that were created in terms of the pragmatism of a functional programmer. It generates virtual versions of the DOM tree, and as soon as changes occur in your application, Om marks the changes between the virtual versions of the DOM tree at regular intervals. It is used to get the minimum number of changes needed for a real DOM tree.
In React, there is a rather important function shouldComponentUpdate, which is used to calculate the difference in the virtual DOM represented by your components. If it returns false, then React will never calculate the children of this component. Thus, React gradually builds a virtual DOM tree to obtain data on those elements that need to be changed.
As it turned out, the default implementation of shouldComponentUpdate is too conservative, because JavaScript developers typically modify objects and arrays. Therefore, to determine the properties of a component that have changed, you must manually go through objects and arrays.
Instead of using JavaScript objects, Om uses data structures from ClojureScript, which, as we know, cannot be changed. Based on this, we can provide a component that implements shouldComponentUpdate, using the fastest check - for equality of links. This means that we can always determine the changed structure in a logarithmic time.
Therefore, we do not need operations like setState, which are used to support efficient updates to tree nodes, as well as a good object-oriented style. Updating tree nodes in Om, starting from the top point, is always faster, because we only compare links on the way down.
Also, because we always redraw from the top of the tree, combined updates are trivial to implement. We don’t worry about supporting combined updates with React, as it is designed to handle these cases for us.
And finally, since we always have an initial UI state for each piece of data, you can simply serialize all the important states of the application. No more worries about the serialization protocol, since Om UI states are always serializable.
It also means that the Om UI returns status instantly. You can easily store any state in memory and you can return to it whenever you want. This is an efficient use of memory, since the data structures from ClojureScript are implemented using memory sharing for them.
Final thoughts
In conclusion, I do not think that the current generation of JavaScript MVC frameworks have many perspectives in the future. I believe that if you sit and think about it, you will get something similar to React / Om. This can provide an optimal balance between simplicity, performance and expressiveness. There is nothing that was not known before ... If you start to perceive the browser as a means of remotely rendering pages and stop storing any garbage there, then everything will work much faster. Sounds like something familiar, right? Yes, like computer graphics programming.