This post is only meant to be a snapshot of the current state of the various DOM virtualising webframeworks that are around. I’m partly publishing it to try and discover more that I may not be aware of.
Many of these frameworks trace an ancestry back to Om and React. However each one tries to deal with perceived problems with the original frameworks. The most common being that React is too heavy and opinionated while not providing a consistent data model for components. Om on the other hand is in Clojurescript and therefore represents too much to learn in terms of a new language and build process.
Most of the libraries build on a few common building blocks that I’m not going to elaborate on here. Virtualdom was an early attempt to separate the core idea of React from the rest of the library code. Virtualdom is only concerned with creating, manipulating and stringifying DOM structures in-memory. Browser DOM APIs involving linking to the actual rendered document so managing virtual DOM is more efficient and simpler because you’re not interacting with these underlying libraries.
Omniscient doesn’t suggest an alternative to Om’s CSP, instead providing a mechanism for passing event flow functions down the component tree. You’re free to choose your own event libraries. It also means that you’re free to make your own mistakes here as no guidance is really given as to how to structure your event scheme appropriately.
Omniscient is one of the earliest frameworks to re-implement Om and therefore has one of the better sets of documentation on its Github pages. That said there’s not a lot of documentation and the framework does not have a massive community. The situation is worse in most of the other frameworks though so this might tip you over in favour of Omniscient.
This is a bit of a Guardian shout out as the primary developer Rich Harris is a Guardian interactive developer.
Ractive (Github) is a little be different from the other frameworks as you can essentially think of it as Mustache templates backed by Observables. You declare a data-binding and write templates in normal Mustache syntax but behind the scenes Ractive is driven by changes in the data and then writes new section of DOM in-memory according to what has changed rather than DOM diff’ing.
Also Ractive sticks with two-way databinding rather than unidirectional data flow so failures in synchronisation or rendering can be problematic.
Mercury on the other hand prides itself on modularity. A microframework it attempts to create a glue layer that allows other libraries to interact in a sensible and consistent way. The default components are Virtualdom and its own observer pattern to wrap state.
Mercury’s biggest problem right now is its lack of documentation. There is an expectation that you are going to read the source code to understand what the framework is doing and how to interact with the API. I frankly think this is unrealistic. The project doesn’t currently supply the incentive to do that. Unless you have a very particular desire to avoid any framework lock-in or you want to use a very specific combination of libraries that is not supported elsewhere its hard to understand why you would invest your effort here rather than in frameworks that offer more support.
Cycle is similarly experimental, its biggest claim is that it is truly reactive and that the rendered page is purely the result of change in state. The introduction is couched in computer science theory but it would seem that at its heart Cycle wraps RxJS and Virtualdom in a glue layer that has the programmer writing the transform sequence between the event and the DOM structure.
I think it is a positive feature that Cycle re-uses a popular library to manage its state-transitions rather than implementing yet another custom version of the Observable pattern. It also makes the framework easier to get started with if you are familiar with the Rx.
Using established libraries also makes the lack of documentation more acceptable as the Cycle readme only needs to explain how the glue works in the framework.
As something built on reactivity you have to get used to dealing with intermediate state which can be bit difficult for the beginner.
Essentially any event where the user would expect feedback means you need write the conditional structure in the output. So if the user types a character in an input box then you need to write the value of the input box to be the characters the user has typed so far. Most frameworks work at a higher level of abstraction or rather they map closer to the DOM APIs, so getting a working application means grokking the way the dataflow works.
If you’re looking for purity (and a resulting simplicity in implementation) but not to have to learn a bespoke API Cycle is nicely positioned.
WebRx is similarly built on top of RxJS Observables but is a much fuller-fat framework that is much more a spiritual successor to Knockout than owing much to the influence Om or React.
Rather like React WebRx doesn’t really provide generalised event handling but instead has special sauce bindings for DOM events and a MessageBus system built over Rx.
It is also written in Typescript and generally looks to play well within the Microsoft ecosystem. It’s interesting to me as an example of how different a language has to be before its regarded as a barrier. Clearly the use of Typescript means there are people who will refuse to use the framework regardless of whether it works for their use case. Other people are going to be attracted exactly because it uses Typescript.
Language choices are also interesting in Deku which is another attempt to re-implement React in a superficial way.
Deku makes use of ES6 and 7 features and doesn’t aim to support a broad range of browsers (unlike say Ractive). Again that is going to rule it out for some people but this is a more interesting as now we are within dialects of the same core language. Language choice for implementing frameworks is not straightforward. What are you looking for? Conciseness? Editor support?
It does however still use JSX which is quite interesting as the framework claims to be taking a functional approach but actually uses a DSL for all its DOM construction.
The lifecycle hooks are slightly different with more hooks for different stages of the process and Deku uses some interesting function passing to send changed data down the tree to components.
Deku doesn’t take much influence from Om though. It doesn’t have sophisticated event handling and uses mutable data with generous access and callbacks on data write to do re-renders. This means bugs and state issues are no less likely to happen than with any other framework. It does adopt the single atom idea with a single tree representing the app and the app renderer being bound to the body element.
As such if you like the idea of React but don’t want to bound into its concept of how a Component should be defined but do like JSX and trust the implementors to create a better dom diff than Facebook or Virtualdom, this is the project for you.
I’ve only chosen a handful of frameworks to look at here, mostly based on the ones I know, I’m expecting people to point out more in the comments. I also haven’t used all of these frameworks. Road-testing all of them would be a bigger task than just trying to describe the design choices they’ve made.
The most common pattern is to try and improve the rendering time versus React by using different virtual dom difference algorithms. Usually this is combined with Observed variables that provide a Reactive component that allows changes in the data model to be conveyed to the DOM model with no coding required.
Few of the frameworks engage with the functional reactive programming paradigm by building abstract event streams or indeed any abstraction over discrete events.
The idea that the app should be a single data structure that represents the whole page seems to be gaining significant traction with several of the frameworks recommending this as an approach.
The explosion of frameworks resulting from the release of React is, I think, a positive thing. Initially it seems really daunting that you have all these choices but when you look at the real level of difference between them you can see that they are actually quite tightly coupled around a few common and core ideas and that mostly they express differences about the concerns that a framework should have which feeds into the wider conversation about micro or comprehensive frameworks.
Also in Clojurescript there is Brutha (https://github.com/weavejester/brutha), which claims to be less opinionated than Om. I do appreciate a nice Pratchett reference now and again.
I think it is an interesting question as to whether the framework’s language matters as well if you’re not asked to interact with you.
You forgot Riot.js!
I knew I would not be able to discover all the frameworks!
On investigation Riot.js is actually more like a lightweight implementation of Web Components than the other frameworks here.
I would say Riot.js is worth noting here: https://muut.com/riotjs/
Have you tried Elm? If yes, what do you think of it?
I realize that — hopefully there will be a blogpost about Elm some time soon 🙂
Clojurescript has a few alternatives to Om now. Reagent is the most popular after which there’s Rum and Freactive. As for other compiled languages, Elm must be looked at.
You might be interested in Mithril as well: https://lhorie.github.io/mithril/
Pratchett reference? I think you mean re-frame: https://github.com/Day8/re-frame
Leo Horie’s Mithril, which I believe inspired Mercury, is a great and rediculously fast responsive framework which comes in at 12kB, and Muut’s Riot is a great alternative to responsive Backbone at 5kB.
Thanks I’ll take a look at it
Just wanted to point out that Ractive’s two way binding is optional, you can disable it on a per instance level by setting a property to false.
I’ve been looking over riot.js, https://muut.com/riotjs/, a minimalistic react + JSX like framework. I haven’t actually tried it out yet and would be interested I hearing about people’s experiences.
https://muut.com/riotjs is nice for it’s readability. It’s also really small, but this can also be a disadvantage for complex applications that need some of the feature of the full size frameworks.
Pingback: Bookmarks for June 6th through June 7th | Chris's Digital Detritus
You forgot a big one : MeteorJs
Meteor to me is trying to solve a very different problem and while it mentions reactivity in its feature list I don’t think it claims anything special technically in terms of reactive software design. Looking at the code it appears to being doing things with Listener pattern callbacks, which is pretty much the opposite of the frameworks I’ve listed here. If I was being unkind I would say that it was using the general meaning of the word to imply the technical one.
I’m open to a rebuttal post or perhaps more information on how Meteor implements reactive code but its still not something that leaps to my mind on this topic.
Hi RREES, You should check Tracker : https://www.meteor.com/tracker . Everything Meteor implements reactively uses it ( ReactJs integration is on the way in the next weeks/months ). One key difference from other frameworks is transparent reactivity, you can control if want to be reactive or not, It’s really easy to use Tracker without Meteor. Give it a try 😉
+1 on Meteor. It’s using the DDP protocol to make all its client content truly reactive. And yes it controls the data flow via a pub/sub model, which may not be good enough for large and complex implementations, but it’s very powerful for streamlined apps and very fast development.
Fast development leading to an app that can’t be large or have complex interactions is surely just tech debt?
Depends on what kind of app you’re writing. A blogging platform? A Slack clone? Live-Editing or code collaboration tool? Meteor is perfect for that kind of thing.
Blame the developers, not the tools. I saw great and terrible projects built with Meteor. So far the community reports that it’s possible to scale Meteor to large applications.
Pingback: Links & Reads from 2015 Week 23 | Martin's Weekly Curations
http://vuejs.org so clean and well documented
And a good tutorial series
I recently bolted virtual DOM onto an existing Backbone app using https://github.com/fiduswriter/diffDOM, only used it for some specific views, super-lightweight and zero framework lock-in. Trivial to extend Backbone.View to integrate the virtual DOM.
There seems to be a consistent theme to the idea that this post was in some way about virtual doms, which are obviously part of the solution but I think if you still have mutable two-way binding data structures you haven’t really got the fully benefit of the approach that Om suggests.
There doesn’t appear to be anything really functional in Mithril, in fact its component model seem to be explicitly object-orientated. Even if you have a pure-view function it doesn’t appear to guarantee any efficiency in rendering either. It’s primary claims seems to be that it’s small and fast for certain common applications.
MObservable is interesting as well, provides observables similar to knockout (and combines well with React), and is simpler in usage comparted to bacon.js / RxJS, see for example this JSFiddle https://jsfiddle.net/mweststrate/wgbe4guu/