From React to Riot 2.0
Tero Piirainen • 2015-01-23
This highly popular blog entry was the starting point for our explorations in minimalism. The point of the writing was that Muut couldn’t be built on top of the popular frameworks: Backbone, Angular, or Ember.
We want our client application to be small. It’s unacceptable that the underlying framework is bigger than the application itself.
We want a small framework API that we understand thoroughly. We want to be able to make sense from the stack traces. All the popular frameworks come with too many API methods, properties, and personal flavors. Full control was especially important as we had a plethora of special needs on a fully embeddable forum software.
To some extent we questioned whether anyone needed a framework at all. As long as the API (or model) is separated from UI the biggest troubles are gone. With events you can build isolated components and native
pushState gives us the ability to deal with back button.
This reasoning worked as a basis for Riot 1.0.
Riot was a proof of concept for the “Frameworkless" blog entry. What would be the most minimalistic MVP (Model-View-Presenter) stack? It started out as a side project but the educational trip became more serious towards the end. Eventually Riot 1.0 came out with following features:
Model View Presenter (MPV) pattern for structuring applications.
observableinterface for separating API (model) from the views and building isolated modules with events.
A router that takes care of URL and back button.
Riot 1.0 was a big success. Obviously not for everyone, since it was so different from others. It was either loved or hated, and not least because it came wrapped in some strong opinions.
No need to remember which elements are bound to which JS event for example. All the dependencies are neatly in one place, the component.
“Templates separate technologies, not concerns.”
Thank you for this insight, Facebook!
Problems in React
Minified React weights 124K, which was an issue. We cannot force our end users to load big 3rd party libraries on the embedding sites.
A big codebase is sometimes a sign of unnecessary complexity. Batching, sub-tree rendering, dirty checking… there must be a simpler way.
The syntax was too verbose for our taste: a lot of React-specific idioms, too many colons and curly brackets, a big list of method names to remember. Just too much “boilerplate” for our uses.
JSX was almost there, but we were looking for a way to unify HTML and JS with less pain.
React has a custom event system and a list of “supported” HTML tags. We didn’t like these specialities and wanted to work with DOM just like before.
Could we build something like React but without the aforementioned concerns? We knew we wanted one for ourselves, and so Riot 2.0 was born.
We borrowed ideas from Riot 1.0 (minimalism), React (virtual dom, components) and HTML5 components (custom tags).
riot- data attributes or other personal flavors.
We exceeded our goals. Riot 2.0 is much smaller and simpler than anticipated. Not just 10× smaller, but 24× smaller than React, and with only 9 public methods on a complete application stack.
Upcoming versions of Riot will include following:
Browser compilation similar to what LESS or JSX do avoiding the build phase on the server. Our compiler is small and fast so it’s not completely crazy to this on production as well.
Server side HTML generation. This is a hot topic nowadays, and lets you build so called “isomorphic” applications. This should be fairly easy to implement for Riot 2.0 since HTML generation is already on the core.
Server side tests. Bigger test suite working on server and client (using jsdom or similar).
Tag option validation using HTML attributes. Something like this:
<my-tag option1="Object" option2="String:required"> </my-tag>
We are also planning to make performance comparisons to other frameworks.
Admittedly, the shift from 1.0 to 2.0 is big. But we believe that 2.0 is much better. Custom tags seem to work and we use them heavily on this production website.
You should definitely give them a shot.