
Show HN: Espresso.js – React Meets Backbone for a Minimal MVC - akrymski
https://github.com/techlayer/espresso.js
======
jbhatab
The docs are sparse. Can you briefly explain why this is awesome?

I actually use backbone and react right now and love it. I also thought flux
was too much, so I'm very interested in a framework like this.

~~~
akrymski
I believe it combines the best ideas of React & Flux & Backbone:

\- A small library that you can read and hack easily

\- No templates or HTML/JSX in your JavaScript

\- Models & Collections are small wrappers around Objects & Arrays

\- Declarative DOM representation provides a simple binding between views and
models (optional)

\- One-directional data flow

\- Child components are managed automatically (no zombie views)

\- Proper Collection.set performs a smart update without relying on sorting

\- Built-in List component for displaying a list of models

~~~
lhorie
Hi, I'm the author of Mithril.js (another small framework).

This is very nice. I just have a few questions:

\- is it possible to reuse markup from one place in another without copy-
paste? (e.g. let's say I have a pagination control that I want to display both
above below a table)

\- how would you hook a third party library (e.g. let's say I need to use
select2.js or pikaday.js)?

\- is it possible to render things on the fly? (e.g. asynchronous modules) or
does all of the HTML need to be on the page on page load?

~~~
akrymski
> is it possible to reuse markup from one place in another without copy-paste?

sure, you can just place the markup in a hidden div and clone the node. or you
can pass a string as the view name:

new Controller({ view: 'node-id' })

and the framework will do that for you: document.getElementById('node-
id').cloneNode(true) and cache the node as well

we typically have a hidden div which contains all re-usable nodes that the app
needs

> how would you hook a third party library

you can do anything you want in the init() method, just like backbone.
this.view is the view node, and you also have access to this.ref[node-name].
you're not forced to user the render sugar the framework provides at all, eg
the List class doesn't use it and updates the DOM imperatively.

> is it possible to render things on the fly

you can always fetch html from the server and do createElement() to generate a
node from that, or inject the html/template into the page body. if you prefer
to have html templates separate, you can just have your build script inject
the templates into the body which makes the app much faster anyway in my
experience.

------
tjelen
OK, this is an interesting approach. Here are some notes from reading the
source:

\- Basic model classes: Model and Collection similar to Backbone, but much
simplified (no REST-API stuff, validations etc, it's basically just that
events are fired when data is changed)

\- There are no templates, all or most of the markup is already present on the
page

\- The Controller class is attached to a DOM element. Specific nodes (called
'refs' as in React) inside this element are denoted by the "data-ref"
attribute. These are collected by the controller during init phase and then
their state is managed via the render() method.

\- there's a special List controller which can be connected to a Collection.
It manages a list of sub-Controllers (each attached to an item in the
Collection)

I like the simplicity. It's very similar to what I'm using lately for smaller
projects.

~~~
akrymski
May I add one more point:

\- the render() method provides a way to declare what the DOM looks like
(React-style) OR manipulate the DOM imperatively (Backbone style)

This helps the Flux one-directional data flow, which you can see in the ToDo
example. Controller's model is actually its internal state by default, so all
data mutation must go through the main data store.

Thank you so much for boiling it down to the key points, I've been struggling
to explain the details clearly. Really the best way to understand what's going
on is to read the ToDo app as it's only 100 lines.

We are using this for PhoneGap and node-webkit apps, it's a perfect for for
mobiles where you need fine-grained control over memory and performance, and
you know the runtime you're developing against (webkit) so there isn't a goal
to get this running across every browser like React or Backbone.

------
daveidol
So how does this compare to actually using React/Flux? It looks like all the
virtual DOM stuff no longer exists, which seems to me like you would lose a
lot of the niceties of React. Why not just use the actual Flux architecture
with Backbone as stores and React as the view?

~~~
akrymski
Few benefits:

\- no need to diff the whole DOM tree

\- no need to write JSX, you can simply use DOM nodes

the render() method still gives you _most_ of the niceties of React, ie a
declarative view of your DOM, without the nasty inclusion of HTML inside your
JS controllers.

PS ToDoMVC performance benchmark shows the to-do app to be about 3-4x faster
than React.

~~~
paultannenbaum
My guess is the performance benchmarks would be much different if you are
dealing with an app with a high number of nodes where the diff/repainting
benefits of React really kick in.

~~~
akrymski
Espresso.js diffs as well, except it doesn't have to diff the entire DOM but
only the attributes that you'll actually be changing in effect.

Moreover it gives you the option between declaratively specifying the DOM to
imperatively manipulating it when you need to for performance reasons.

It's a tiny library and the approach is much more efficient than diffing the
virtual DOM for the entire page, so I'm pretty confident that results would
actually be even better in larger apps.

------
krazemon
This definitely seems like something I'd like to use and also contribute to if
you are interested. One question I have is, how do you imagine routing being
done? I don't see it in the examples so I was curious if you have ideas about
this.

~~~
akrymski
ToDo example actually has simple routing. I'm using this mostly for PhoneGap
projects so don't even use routing, but any routing library should work same
way as in Backbone, eg:

[https://github.com/flatiron/director](https://github.com/flatiron/director)

Thanks, would be happy to accept contributions!

------
hardwaresofton
Looking at the todo example, I don't see any of the usual React code for
creating/managing components...

Is it just React the pattern (without the component part)?

~~~
akrymski
Controllers are equivalent to React's components. the render() method lets you
include child controllers:

[https://cdn.rawgit.com/techlayer/espresso.js/master/docs/ind...](https://cdn.rawgit.com/techlayer/espresso.js/master/docs/index.html#controllers/render)

~~~
hardwaresofton
Yup, I totally missed the docs -- my mistake, was too hasty

Would be nice if docs were higher up on the README though

------
couchand
It doesn't look like there's any separation between the model and the view, so
in what sense is this MVC?

~~~
dreamdu5t
It's not MVC. There are no controllers, and data in a Backbone app does not
flow in a circular fashion. I consider Backbone views describable as
presenters, and Backbone describable with the Model-View-Presenter (MVP)
pattern.

MVP diagram:
[http://lostechies.com/derickbailey/files/2011/12/NewImage2.p...](http://lostechies.com/derickbailey/files/2011/12/NewImage2.png)

Why Backbone is not MVC:
[http://lostechies.com/derickbailey/2011/12/23/backbone-js-
is...](http://lostechies.com/derickbailey/2011/12/23/backbone-js-is-not-an-
mvc-framework/)

~~~
couchand
Not sure if your comment is directed towards me or the OP. However, there is
in fact a Controller class in this project, so you may be confusing this
framework for vanilla Backbone?

~~~
weego
There is a Controller class, but in the demo app you can see that both App and
ToDoItem extend Controller, which makes be believe that Controller is perhaps
not what you'd expect.

Having said that, I much prefer Backbones presenter idiom over MVC.

------
mc_hammer
this is so gud

