Riot.js – A 1kb client-side MVP framework
moot.it
moot.it
This sort of thing is a beautiful demonstration of marketing, big promises, and bombastic rhetoric in open source. But one of the best things about open source is that you don't have to take such claims at face value. If you actually look at the source, you'll find:
https://github.com/moot/riotjs/blob/29ae687ca0633b703e124331...
* A funny syntax for string interpolation. (Not templates)
* A strange bug relating to "popstate", ignoring browser support for folks on IE.
* A simple proxy to jQuery's `on`, `off`, `emit`, and `one` functions. (Why not just use jQuery events directly?)
* A simple proxy to "pushstate" and "popstate". (Ditto)
... and that's about it.
Calling this, "The fastest, smallest and most powerful client side framework for building large scale web applications," is pretty funny stuff — but I guess it might also be true. There's almost literally nothing here except for jQuery.
That said, if this were rewritten as a "you don't need a library to do MVC" blog post, then more power to it — it would be right on. But at the moment, it's a pretty spectacular piece of puffery — the sad thing being just how effective this sort of thing can be: http://cl.ly/SFzy. "Riot.js" might be a particularly egregious example, but similar tactics can be found all over the place. As a community, it would be nice if we could spend a little more time reading source, and seeing what libraries actually do and what can be done with them, and less time just drinking down the PR.
(And if this is all an elaborate joke, then I'm an ass for falling for it ;) But that's not the sense I get.)
I would not write my own event library from scratch if I can take advantage of jQuery. Can you elaborate what's wrong with proxying?
I wouldn't take the criticism to heart. The bit about bragging about how fast and small it is will always create friction - especially when another big library is needed to make it useful.
Also the result isn't as expressive as, say, Angular. You say that's a good thing:
"Current data-binding frameworks promote the use of spaghetti on the HTML layer. Suddenly the onclick attribute is back! (I'm looking at you, Angular)."
But you neglect to mention that the tradeoff is all the boilerplate you're going to have to write.
Also, you'll have to pry two-way data binding from my cold dead hands.... :)
Second, even if it did (again, it does not), it comes at the cost of reduced functionality. You can claim that these are unnecessary features, but, for instance, the entire template is not re-rendered on each change in Angular, only the affected piece. If you think that that's the right way to write apps in riot, then that means that every line in your app dedicated to restricting changes to a part of the view is boilerplate.
It doesn't have enough features to require or demonstrate the abstractions needed to eliminate boilerplate.
That being said I like what you did with Riot which is basically use plain JavaScript as much as possible. And I also like to you bring attention to the fact that jQuery doesn't cause spaghetti: programmers cause spaghetti.
Riot's TodoMVC - 59 LOC html, 185 LOC js.
Angulars TodoMVC - 70 LOC html , 145 LOC js. ( I DINT even discount the extra lines used for comments and stuff - which angulars has quite a lot of ! ) . https://github.com/tastejs/todomvc/tree/gh-pages/architectur...
The other implementation is 71 html and 162 js. https://github.com/tastejs/todomvc/tree/gh-pages/architectur...
Stop claiming that your "framework" allows writing less loc.
There are sooo many useful constructs that all these frameworks provide. I generally abhor Backbone for its "minimalistic" approach. But looks like even jashkenas is taking issue to what you are doing here.
You are saying that / claiming that - me / we are soo damn good that we can do in <1KB what a whole bunch of developers have not been able to do in xKB where x is a larger number.
why are you lying and thinking you can get away with that ?
If your project doesn't use jQuery feel free to use the right tool for the right job - I can't remember the last time I worked on a web project that didn't have jQuery.
The project might as well just be a blog post with what I'd consider the only useful and non-hyperbolic aspect which was:
> What people refer to as spaghetti is in fact a mixture of model and view code. To avoid it, simply separate your model code from the view with observables.
Fine. I agree that people shouldn't falsely miscredit jQuery for causing spaghetti code and understanding basic separation is valuable. Unfortunately the following line is one of hyperbole:
> You don't need a framework for that.
Which I have a problem with for 2 reasons:
1. That is not all frameworks do. They also reduce the amount of boilerplate, repetitive code you have to write. Riot.js does not appear to do so (significantly). Look at the amount of code in the TodoMVC example's model [1]. That would be dramatically less code when using Backbone.
2. Nobody needs a framework. But frameworks establish conventions and conventions are very valuable for collaboration as well as general discussion of patterns and ideas.
And as for:
> Current frameworks persuade false beliefs with shiny websites and finely crafted marketing without transparent, scientific analysis. They solve hypothetical problems and cause new problems instead. Unfortunately, large communities are dealing with irrelevant issues.
Seriously? I want to swear and throw things, and I'm not even a framework author.
[1] https://github.com/moot/riotjs/blob/master/todomvc/dist/todo...
The amount of Todo MVC code in Riot is actually smaller than in Backbone but like I say on the post the focus should not be on the code size but on simplicity – and this is why Riot advocates MVP a lot. Actually Backbone also seems like a MVP framework to me.
Also, the "toggle all" function uses a `filter` variable that's undefined AFAICT.
I'm not trying to knock the framework. I like what I see. Just a little hard to follow along when I'm not sure if the code is wrong, or my understanding of it is.
I've used $.bbq plugin for 'basic' routing (similar API to riot).
It wasn't enough. I was writing tons of boilerplate and my routing logic was fragmented and hard to follow. Sure, this comes down to lack of convention, but that's as I said, a benefit of frameworks that establish said conventions. I'm also not much of a fan of Backbone's router by the way. Ember's on the other hand, looks bloody fantastic.
I've tried every templating language under the sun.
The idea of creating portable/pure HTML/logicless templates (whatever you want to call them) so that your 'HTML developer' can work with them is a fool's gold. If your 'HTML developer' is likely to misunderstand or break your HTML because it contains logic in it, they're just as likely to do the same when there are implicit rules in your templates. If anything, explicit template tags, like say an {{#each}} tag makes them far more likely to tread carefully when dealing with them. But in reality I've found this is all a non-existent scenario. The (JS) developer is going to be the one writing the HTML and translating a designer's vision into the web-app code. That developer is likely to need to refactor templates/partials several times over the lifetime of the app. So whether the designer creates their style-guide as HTML & CSS or not, you don't want them working on the actual app's templates. It seems to make way more sense to have them working on static playground version of the app's markup.
Collections. Boilerplate.
Backbone's Collection and Models are really great and the create/add/save stuff cuts down on a lot of repetitive code. The Underscore functionality you get on Collections are fantastic for opening up your console and exploring your app with powerful things like:
App.Models.people.pluck('age'); // spit out ages in array
App.Models.people.where({ age: 18 })[0].set('age', 19); // see what happens in your view as a result
App.Views.funkyInspector.model.set('active', true).save(); // see what happens in view/xhr as a result...
Riot doesn't give me this. Basically you're not doing enough for me!It is all marketing. Notice how shiny Angular/Ember's site is? Open source mindshare is not determined by technical superiority! There is plenty of marketing, hype, and fashion that controls it.
Big paintbrush here, but many devs don't seem to care a lick about how composable things are. They just want to learn someone's 'opinionated' API, and then bet their entire design on it. They'd rather dig through error messages, and obscure edge cases instead of learning how to structure their code so they don't need to rely on frameworks for everything. When faced with a new platform, they'll jump into whatever everyone else is using at the time, rather than starting with the core tech and building up until they hit a need.
Frameworks are great for MVPs, though.
You realise how absurd it is to say that just because a project has a nice website it is all marketing? I genuinely thought you were being sarcastic and agreeing with me before your next sentence!
> Open source mindshare is not determined by technical superiority! There is plenty of marketing, hype, and fashion that controls it.
There's a degree of hype around anything that requires publicity to bring it to people's attention, but that doesn't justify trashing valuable projects with lazy generalisations. I have watched dozens of Angular and Ember talks and demos by this point and have never once thought "wow this is a load of hype and fashion, nothing to see here". Listen to Yehuda and Tom from Ember being interviewed and tell me those aren't guys that genuinely want to make app development better.
> Big paintbrush here...
No kidding! I'm not aware of any devs that intentionally wish to make their lives a misery in the way you suggest.
But, as you said, there is hype/publicity with OSS. I wanted to emphasize that is not a pure meritocracy, even within OSS. If people aren't ready for your project, then it won't be adopted, regardless of how good it is. It is very similar to consumer technology.
Regarding composability: what are your thoughts on communities (like Clojure's) that consciously reject the notion of One True Framework?
Probably :) Of course though, I do think we should all be aware there are people on the receiving end of these comments we casually fire at frameworks that have worked crazy hard on those projects. (Listen to this episode of The Changelog with the maintainer of Capistrano if you want to hear some evidence of the effects of this [1]). Vague, dismissive comments can sometimes be the hardest to hear.
And yeah, I suppose sweeping generalisations are a massive bugbear of mine. At my previous job whenever I heard one heading my way I knew I was usually in for a ton of work to correct them so that we could _just do sensible work_. I think I have PTSD from that experience. :)
I physically shudder when I hear the word 'bloat', for instance. (It's usually followed by some amount of ignorant tosh from someone who hasn't learned what that 'bloat' is there for).
I think I'm discussing the celebrity culture around these frameworks more than the frameworks themselves. I don't have a problem with them technically, they're a bit beyond what I could make. But I don't want to see classical notions of program design phased out in favor of "just use X." The ideas of what makes software malleable, pleasant to maintain, and grow are quite old.
It would be great to use a small component (like riot.js say) with other nimble components.
And, you know, the reason it's < 1k is that it doesn't really seem to do anything jQuery can't do with about the same amount of boilerplate.
True. There's 0.85kb + license.
I think that's the point.
Marketing is so much more than just positioning of a brand. Big promises of Riot.js is exactly that -- positioning. And positioning is identifying and attempting to occupy a market niche for a brand.
Marketing hate is a pet peeve of mine and a reason for my ramblings on this topic.
Another quick note: what you're calling a View in riot.js is actually a Template and your Presenter is probably more of a View than a Presenter.
This is almost identical to Backbone which can also be interpreted as MVP, see:
http://lostechies.com/derickbailey/2011/12/23/backbone-js-is...
EDIT: ok, now I understand. It is a joke, because all this long article boils down to just one sentence, repeated throughout the article itself: "You don't need a framework for that."
Well, I don't claim to take all my decisions based on pure reasoning. Intuition has a lot to do with my technology choices, because it's built on all my prior experiences and knowledge. I've learned that often keeping it simple is a good thing. There´s a tendency to over-architect and over-abstract, and the cognitive overload of the full stack, end-to-end, is significant.
For front-end JavaScript applications, I've been favorable to AngularJS and Knockout. I've looked into Backbone but it promotes a style of programming I'm done with and I want to have no relation to ever again, so I wouldn't consider Backbone an alternative either way.
So I don't feel diminished or discouraged by negative remarks to say that I'll try Riot's style in the next small app I'll build. It's targeted at mobile, it already depends on jQuery, and I was worried to add another large (for 3G) dependency to it.
---
But hey, if you want to try out a hot new framework that Fits in A Tweet™, I've got something special for you.
Announcing Revolution.js
It's a mere fraction the size of Riot.js, and provides over 100 times the functionality. Despite the unbelievable size, all the building blocks are there: a template engine, router, event library and a strict MVP pattern to keep things organized.
Revolution.js is simpler and faster — in fact, on a completely different scale. In fact, it's so small and so fast that I can share it with you right here:
function Revolution() {
var a = arguments;
return jQuery[a[0]].apply(jQuery, a.slice(1));
}
New frameworks like Riot.js persuade false beliefs with shiny websites and finely crafted marketing without transparent, scientific analysis. They solve hypothetical problems and cause new problems instead.At this point you might ask — "Hey, wait a minute, what's the deal? Isn't that just wrapping jQuery, and adding nothing?". To which I would answer, yes, exactly.
This is a Revolution against the status quo! Revolution is a manifesto for vanilla JavaScript and jQuery.
I think that's really the point. Rejecting the idea of these big frameworks and promoting vanilla JS.. Rejecting the myth that without big frameworks your code is unmanageable.
Arguments object has no method `slice`.
Steps to repro:
Invoke the constructor.
I'll send a PR as soon as this makes it to Github.
--------
In all seriousness though, I completely agree with you.
So far no reasonable arguments why Backbone is better. Is it just larger, slower and less effective? I was expecting you to argue against those points that are now clearly visible to everyone.
> Current frameworks persuade false beliefs with shiny websites and finely crafted marketing without transparent, scientific analysis. They solve hypothetical problems and cause new problems instead. Unfortunately, large communities are dealing with irrelevant issues.
You're telling jashkenas (indirectly) that he "persuade false beliefs", "without scientific analysis", that he's solving "hypothetical problems" and "dealing with irrelevant issues" and plenty of other things like that... and what response do you expect from him?
> I was hoping you were closer to a scientist.
You already told him he's not a scientist, see above.
P.S.: I don't follow any "religion". I use framework or plain JavaScript depending on the project, and I find it sad when anyone promotes their solution as the only good one.
The blog entry states that you can implement the Todo MVC app with 1kb of extra code on top of jQuery and the end result is smaller, modular and faster. This is big news.
The statements on the post are indeed bold but I think they are still valid. They should deserve a better response IMHO. This seriously questions the relevance of current client-side frameworks.
Without constructive criticism should we just agree that others are bigger, slower and less productive ??
- Comparing template engines only (with the riot solution having less features) doesn't give a complete picture for comparing speed. There are dozen of other parts to make a web app. The template is only a small part. Benchmarks aren't even a good way to compare speed. It's how the user feels when using the resulting app and interacting with the UI that matters.
- TodoMVC is a very small app for comparing productivity. E.g. your router implementation doesn't take into account IE bugs, and researching such bugs instead of using a proven solution can be less productive.
I agree with you that modular and maintainable web apps can be developed with jQuery only, and even plain JavaScript only. I dislike, as much as you do, "Backbone developers", "AngularJS developers", "Ember.js developers", etc. who can use only one framework, can't properly structure an app without using a framework, and claim that the framework they use is the only good one to solve any problems and build any type of app.
A good developer should be able to choose the proper solution for a particular problem. There's no one size fits all solution for every problem.
Actually I think it is a joke. Kind of. It's an elaborate argument for a philosophy (basically: eschew frameworks, use jQuery for DOM and events, manage your own MVP structure).
They go on to say "You don't need a framework" (repeatedly), and "Riot is a manifesto for vanilla JavaScript and jQuery".
I see it as a functioning demo to present an opinion about how apps should be written. Viewed like this, the whole "world's fastest framework" thing seems tongue-in-cheek. Their use of the familiar "Unveiling a new framework" device is a conceit to push a philosophy. It's allegorical.
I admit that starting off with silly benchmarks undermines the point a lot :)
I totally appreciate this effort. But if I were to try the same thing, instead of creating a Model structure (which could easily be handled with plain JQuery itself), I'd put more thought on the Presenter.
But hey, I didn't, and this guy did, so much appreciated indeed. This is certainly an inspiration, time for everyone to think "What does your project need?" vs "What does the framework provide?".
Even if you're inclined to argue that this style of programming doesn't lead to a giant mess (and I'm inclined to believe that it does, even if you are the most disciplined of programmers) I still don't see the benefit of adding this 1K of JavaScript to my page at all. I can duplicate $.observable with a vanilla jQuery object.
To call this the "most powerful client side framework for building large scale web applications" is downright laughable.
The problem with the typical 'jquery-type' programming was that apps were essentially an ad-hoc collection of (sometimes massive) event handlers. I think the problem boiled down to:
* there wasn't much experience and consensus on how to organise javascript code (split it into module etc.)
* the DOM is global, meaning you can register event handlers to anything from anywhere (To make matters worse events bubble up and down the DOM tree)!
It seems like people immediately resorted to extremes to solve these issue - basically trying to abstract away the DOM and even javascript completely - whereas the solution could be something much simpler and subtler.
Most developers don't bother about the presentation layer and they think that jQuery is a pain but most front-end designer and developers rely on it.
Great step.
... but, if you're going to test Underscore templates for speed, you need to use the `variable` setting to avoid the `with` block.
https://github.com/moot/riotjs/blob/master/compare/speed/ind...
The $.each has only 4 iterations and has no effect on the stats.
> a templating engine could easily avoid the actual with
> statement but provide same convenience
I'm afraid that's not possible. If you look at other micro-templating libraries that allow arbitrary JavaScript values, you'll find that there are two options. Either you can support naked variables, and you have to use "with" to bring them into scope ... or you have to prefix all of your variable accesses off a "data" object, which is less ergonomic, but faster. Underscore supports both.If you've got a patch that is able to do otherwise, I'd love to see it ;)
I am sure you realize you can just walk the AST for what identifiers are being used in the template code and forward declare them in the generated code so that reference errors are not caused.
At compile time, you have no idea which identifiers are incoming data values — to be supplied by the caller of the template function — and which identifiers already exist in scope.
<div>@hello</div>
The generated code can be like (not including runtime lib): var ___html = "";
var hello = hasown.call(data, "hello") ? data.hello : "";
___html += '<div>' +
safeString(hello, HTML_GENERIC) +
'</div>';
return ___html;
Which gives same effect as `with`._.template("Using 'with': <%= data.answer %>", {answer: 'no'}, {variable: 'data'});
I could do this with pre- compilation. Possible?
With that being said :
> Here's the shocking part: a 1Kb library requires the least keystrokes to build the Todo MVC application
I'll decide on my own if it's shocking or not. Also I don't care that much about keystrokes, there's nothing wrong with verbose/expressive languages. I want my code to be readable and maintainable, and then concise if possible. This project looks cool but I wish its creator(s) was/were a bit more humble.
And I totally agree that the goal should be readability and maintainability – this is what the post is mostly about.
I get what you're trying to do here but please don't resort to misleading statements to prove your point. This community sees right through it and every time you say things like this, you lose credibility.
To remove the jQuery dependency I'd suggest looking at this: http://minifiedjs.com/
A couple code notes:
* why, in the observable function, are you switching functionality not by the name of the function called ('on','emit', etc.) but by the index of that function name in the array on line 32? This strikes me as brittle because adding to or rearranging that array would cause the whole function to fall apart. It's also harder to read- I'm looking at `if(i == 2)` rather than `if( fnName === 'emit' )`. Does this yield a significant performance gain or is it just to juice the final "weight" of the library (<1kb)? I ask because it sure as heck makes the code harder to read.
* Using `name` & `names` as variable names makes the code harder to read, as it doesn't give any meaningful context about what the variable stores (besides the fact that it probably represents a thing that has a "name"). It looks like in this case it represents event names but more descriptive variable names would eliminate this ambiguity & it would make no difference to the code weight after minification.
I bring these things up because this lib looks cool & I like the "you can easily read the whole source" point, but this obsession with brevity (that's what it looks like at least) causes code readability to suffer & greatly diminishes the benefit of being able to "easily read the whole source." Make the code more readable & more people will use the project & contribute. :)
By only supporting simple single property accesses. All that this can do is print values from an object — no loops, conditionals, filters, methods, or anything else — like the others support. Think string interpolation, not templates.
Angular has no dependancies. Knockout also has no dependancies, so it's actually 13k > than riot.
For anyone who really serious about going minimal, here are some alternatives to jquery to build on.
9.7kb http://zeptojs.com/ 3.4kb https://github.com/rpflorence/snack 5.0kb https://github.com/julienw/dollardom/ 10kb http://xuijs.com/ <1kb https://github.com/honza/140medley
What a riot!
Most of us aren't building "Todo" apps. We're building bigger apps which require - or are more suitable - for a framework like Angular/Ember. That's just my 2 cents.
I just dislike the use of "new" in javascript...
One of the reasons this is so light is that it forces you to write boilerplate code for models. I use libs to eliminate boilerplate, not force it upon me.
What a weird factor to use for choosing a template engine. Also there already is a popular unit test framework called riot.js
Not 100% sure what you mean but if you measure the time to render a HTML fragment 100 times the total time is 1 x pre-compilation + 100 x rendering. The pre-compilation has virtually no effect on the total time.
I find the bottleneck is 99% the browser's HTML parser and 1% the actual templating library.
If somebody had any tips on how to bring down the "Parse HTML" time spent in the Chrome inspector (see Timeline), I would be interested to know. Tips other than, of course, "parse less HTML".
(still nice project of course)
In terms of UI development, the Model-View-Presenter pattern has been around (and fairly mainstream) for a couple of decades now, so the target audience will probably assume correctly.
You don't follow a rule, it doesn't allow you to do it. You need to go by the book there, so why not here?
Okay, he isn't.