

Our First Node.js App: Backbone on the Client and Server - AirbnbNerds
http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product

======
jashkenas
I was lucky to be able to catch a preview presentation of this "Holy Grail"
project at SpainJS, last summer. It's _very_ interesting stuff. I think that
one of the more important caveats to mention is that to the extent that your
application is composed of rich interactions, visualizations and
interactivity, and logged-in-user-only content, that stuff tends to remain on
the client-side alone ... but for your basic rendering of JavaScript models to
a flat HTML page, this is a great project to keep a close watch on. In
particular:

* Caching of shared static HTML for fast-as-possible page loads.

* Google indexing and searchability.

* Backbone apps that feel more like a series of pages and less like a single-page app.

... are all things that are addressed quite neatly by Rendr.

~~~
frontendbeauty
Author here (spikebrehm):

Jeremy, I think you're mistaking this for Keith Norman's SpainJS presentation
(<http://www.youtube.com/watch?v=jbn9c_yfuoM>). He proposes the same approach,
but I don't know if it ever got past a demo. Although it seems like they may
be using some form of this at Groupon in production.

Anyway, it _is_ exciting, isn't it? This is just the beginning for us -- we've
had to make a few hacky design decisions to be able to ship, but I think we
will get the kinks worked out. The trick, and the challenge, seems to lie in
choosing the right set of abstractions to hide the code complexity from the
application developer. I hope to open source it as soon as I can, to benefit
from the input of luminaries such as yourself!

Oh yeah, and the offer to give a Tech Talk at Airbnb next time you're in SF
still stands :)

~~~
WickyNilliams
Very interesting stuff :) Can't wait to hear more on this, as it seems like
the panacea we've been slowly moving towards for some time.

How does the approach you've taken compare with the architecture outlined in
nodejitsu's concept of isomorphic JS?

<http://blog.nodejitsu.com/scaling-isomorphic-javascript-code>

------
ianstormtaylor
This is exactly what I've been waiting for. I can't wait til this is open-
sourced! Was just thinking about trying out Angular because Backbone just
wasn't cutting it, but this is going to make me hold out.

Random piece of feedback: it's weird to use data-model_id (instead of data-
model-id). I assume you're trying to match some pre-existing naming convention
(but JS tends towards camelCase anyways...), but I think it would be better to
go with dashes as that is HTML attribute standard. That was the only part that
looked sloppy to me.

Another thought: Did you guys experiment with event-based logic for postRender
instead of pre-defined method hooks? I find the pre-defined method approach
hacky feeling.

~~~
ludwigvan
> Random piece of feedback: it's weird to use data-model_id (instead of data-
> model-id)

I have thought about this one too in my own applications, and I seem to switch
back and forth.

The good thing about using underscore is that the variable name can match on
both sides of the expression:

    
    
        var model_id = $foo.data('model_id');
    

vs

    
    
        var model_id = $foo.data('model-id');
    

Mixing camelCase with dash seems a bit weird for me, because now there is a
delimiter delimited, and case delimited convention: `data-modelId`.

I am trying to use camelCase for new code in other parts of the code though,
as it seems to be the general convention in JS. [0]

[0] <http://ozmm.org/posts/javascript_style.html>

~~~
frontendbeauty
Agreed, the underscore in the data-attribute isn't ideal. I initially tried to
use camelCase, but alas, we often forget that DOM elements are case-
insensitive:

<http://cl.ly/image/2c113k1h1L41>

~~~
ianstormtaylor
Why not stick to conventions and go with dashes? Underscores are out of place
in Javascript and the DOM... If I'm going to be forced to use underscore_case
in Rendr that's different than the rest of my codebase (or other codebases I
don't control which are all camelCase in Javascript) it's going to feel more
unclean from the start.

Or you could say I'm not forced to use it, but now I'm using camelCase for
variables and underscore_case for data attributes... so the two don't match,
so why have the non-standard underscore_case at all.

(This would be an example of one of the things that makes libraries feel
cludgy, and one of the reasons I love how consistent Backbone is, like I was
talking about further up the thread with Jashkenas.)

~~~
frontendbeauty
I'm open to that. Like I've said, there's definitely room for cleanup of the
implementation. Either way, this isn't a detail that's exposed to the
application developer.

------
switz
It's worth pointing out that DerbyJS already renders on the server and the
client without any configuration. I implore you all to give it a shot.

For an example, visit <http://phishvids.com> – try clicking around and then
refreshing or even disabling javascript.

[0] <http://derbyjs.com>

~~~
bherms
Major shout out for phishvids :)

I'd love to help with the transition to Redis if I get some free time in the
near future, assuming you're still looking to go that route.

------
jbigelow76
This is really interesting, although I'm still new enough to node and complex
JS apps that I'm struggling to take it all in. That being said, could a hack-
ish approximation of what Airbnb is doing be accomplished by rendering the
first call of an app in phantom.js and pushing it out in the response stream?

Questions about session state management are popping up in my head but maybe
that's some of the secret sauce in the Rendr portion of Airbnb's app.

Great work guys, this is really pushing the boundaries of full stack app
development with js.

~~~
frontendbeauty
Author here (spikebrehm). Good question. Yep, you could accomplish something
similar by booting up PhantomJS or node-chimera [0] and scraping yourself, but
that seems hacky and hard to scale. Justin Tulloss of Rdio talked about this
approach in his Airbnb Tech Talk [1], saying that the tricky part is
determining when the page is _actually_ done rendering, especially if you have
a bunch of JavaScript that's performing DOM manipulation.

[0] <https://github.com/deanmao/node-chimera> [1]
<https://www.youtube.com/watch?v=TB-l2nF67iU>

------
mmahemoff
Fantastic. This kind of thing, and Meteor, is really what Node is made for.
Till recently, Node web frameworks mostly been "let's do RoR or Sinatra, but
look it's in JS! #Neat". Sure, there's some benefit in terms of developer
skill set and avoiding schizophrenic context-switching; but still, the great
promise of SSJS is running the same actual code on both sides.

~~~
fourstar
To be honest, Meteor is nice and a very ambitious project but the fact that
you are writing an application with it means you are probably wedded to it.

That's why I've been using Express for my middleware, npm modules as needed,
and mongoose as my db wrapper (or if I want to switch it out for redis, I can
do so easily). Not sure how easily I can port my "meteor app" to a different
framework that comes along.

~~~
JPKab
I've been playing with Meteor lately, and I can certainly see some element of
lock in when using it. That scares me naturally. However, the positives are:
1) Speed: It is insane how little work has to be done to stand something up
that is decent and funtional 2) Packages: Not a long list, but the ones that
exist are ridiculously easy to implement.

Seriously, the sheer amount of work that you end up NOT doing almost makes it
feel like cheating. I can completely understand why people don't like it. I
fully intend to build something in Derby soon, and to examine Rendr. But I'm
wanting to build an enterprise focused metadata management app, and Meteor
seems to me to be the right way to go, because at the end of the day I just
want to get something built that provides a capability.

------
fukyeah
That's not the holy grail. I'll tell you what the holy grail is:

A web app that runs completely on CSS.

No need for stupid web servers, but since web servers are handy we'll build
one with css.

And I scoff at HTML; but because of performance I made css compile to html
too.

I'm working on a project that'll I'll be unveiling as my 'open source master
piece'; It's just a little thing I call node.css. That's right, css bindings
to C++. No more stupid C++ either.

Strap on some CSS build automation and what do you get? That's right, the holy
grail. I'll call it CSS on Rails.

What's more, I've already done it and launched my current employers flagship
product on it. Hope it doesn't screw the entire business over the long haul.
Oh well, I can switch jobs if that happens and pretend I never posted this.

------
phatbyte
I'm I right to assume that Javascript might be the next main web language for
back-end and front-end in the next couple of years ?

------
acjohnson55
I'd much, much rather move Django to the client than JS to the server. With
CoffeeScript, this would be more tolerable, but even sacrificing Python, I
love Django's architecture so much I don't want to give it up.

------
dnajd
I'm utterly confused. The main benefit of this approach is summed up in the
paragraph: "Compare this with serving the full search results HTML from the
server.... It feels 5x faster."

But doesn't ruby on rails (and most other web stacks) already do server side
rendering VERY well and are hugely supported by enormous communities.
Javascript is useful for things like infinite scroll, interactive client side
calendars or making browser based games; but a web search is absolutely simple
in ROR and doesn't need backbone or javascript at all.

Don't get me wrong, I love javascript and backbone / angular. But why push
logic to the client side for a search page and then try to pull client-side
technologies back to the server side in an effort to resolve performance
problems that are already solved by existing technology?

In the words of Carl Sagan "why not skip a step". Unless you just love
javascript so much that you're willing to recreate rails on the server side
with it. That would be a sensible reason to do it.

Not trying to troll, just thought I'd throw this perspective out there.

~~~
ianstormtaylor
You're missing the part about how single-page, client-side apps are much more
performant _once_ the page loads. Spike is trying to get the best of both
worlds (hence "Holy Grail").

Server-side gives you fast page load times. Client-side gives you fast user
interaction times.

~~~
dnajd
That was the straw man I was thinking I saw in the post.

Why not use rails to load the page (no BYO framework involved) and then use
javascript/backbone/etc on the client-side; as opposed to bringing the client-
side technologies server-side to accomplish the same thing?

I'm thinking specifically of the search page example that was represented as a
screenshot in this blog.

------
lnanek2
This sort of integration has been happening more and more with the data format
as well for me. After around the third mobile client for a server I'm tired of
native data models and just want the closest thing to the server's (and the
DB's in the case on Mongo) JSON. I don't need it repeated in SQL DML, JSON,
Java, Objective-C, C#...

------
minikomi
The span !important font-family css rule is overriding the gist monospace css
though. Reading code snippets in proxima-nova is .. a little tricky.

That said, very interesting article.

I wonder.. Has anyone tried rendering a page, and then bootstraping your
initial Backbone models pulling data from the HTML?

~~~
2mur
Here is an article about that:

[http://lostechies.com/derickbailey/2011/09/26/seo-and-
access...](http://lostechies.com/derickbailey/2011/09/26/seo-and-
accessibility-with-html5-pushstate-part-2-progressive-enhancement-with-
backbone-js/)

------
paulbjensen
Great article, especially in coming up with a clean way to reaching the holy
grail. I remember seeing in Spike's tech talk some months back that they
initially chose DerbyJS, but it seems from the blog post that they went with
Express instead. Curious to find out why.

------
masiello
Thanks a lot for sharing, I am moving my first steps into this technology and
this really helped :)

------
jacquesc
Really hoping EmberJS gets this feature as well. It's possible now (with some
fancy hacks), but I've read they plan to bake it into the framework (along
with tight rails integration). Basically it just comes down to generating the
initial view HTML on the server (by running the initial api call and render),
then subsequent calls would be handled by the client.

Doesn't have to be 100% Node.js front to back (you can still write your APIs
in another language), but Node provides that handy bridge to get the server
side rendering of client code.

------
l1ghtm4n
I was just thinking about this today. The web devs I'm working with are
talking about ditching Rails entirely in favor of in-browser template
rendering by JS. With a backend also in JS, it seems to clearly be a winning
development environment for new projects today. Just the diminished learning
curve would be enough for me to look closely at this. This is coming from a
very non-front end guy, though, so I might be a little starry-eyed.

------
enoughalready
Hey guys, looks pretty good. I'm interested in the decision to move to server
side templating. You mention that the loading of js, then making an ajax call,
then rendering the page, was slower than just serving up html. Did you guys
try bootstrapping json data server side? That way you could avoid making an
ajax request on load. Do you have any perf numbers to share?

Thanks!

~~~
frontendbeauty
Author here. So, yes, bootstrapping the JSON on initial pageload would be a
lot faster than waiting for the Backbone.Router to fetch it (for the Rails +
Backbone approach). But therein lies the problem I was talking about: to
bootstrap the data for a particular URL, but to also have the client-side
request the proper data for that URL in response to a pushState event, you end
up needing to duplicate the mappings from app URLs to API resources on the
client- and server-sides, and you need to be able to access the same API on
both sides as well.

We avoid this with Rendr by defining routes, controllers, models, etc in a way
that can be run on both sides.

------
jared314
If they add in some generators, and throw in node-webkit support, this could
end up like Microsoft Volta[1].

[1] [http://www.liveside.net/2007/12/05/microsoft-releases-
volta-...](http://www.liveside.net/2007/12/05/microsoft-releases-volta-tech-
preview/)

------
new2
I've been looking for resources on when to use rails vs when to use node.js.
I've been programming in ruby/rails for 2 years and picked up node about 9
months ago. Any tips or resources to learn which tool to use depending on the
problem?

~~~
modarts
I'd think the use case being addressed in the article (having to share
backbone views that can be rendered either on the client or server) would be
the sweet spot for node.

------
mcgwiz
Looks great!

I'd just like to note that those working on Backbone single-page apps hosted
by an ASP.NET site can also achieve this idiomatically, with the use of the
Nustache view engine and controller actions that can do HTTP content
negotiation.

------
mxxx
Excellent stuff, thanks a lot for sharing. The Airbnb tech talks have been
great, you guys are breaking some great ground and it's cool that you're so
enthusiastic to share your discoveries.

------
trungonnews
Have you guys checked out Yahoo Mojito? It aims to solve the exact same
problem. It's a bit cleaner than DerbyJS and Meteor too.

------
LAMike
This looks awesome, hope to use it on the next update to my app which is
running Backbone with Django

------
bjhoops1
I can't wait to see this once it's open-sourced! Holy Grail, indeed!

------
gdonelli
I was excited until I saw coffee script code

~~~
frontendbeauty
While the library (Rendr) is written in CoffeeScript, you would of course be
able to write your application code in JavaScript, or anything that compiles
down to it.

