Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Render Backbone.js application on the server AND the client

Supposed I have a web application that is built using Backbone.js and Handlebars. As server I am using Node.js. Now I want to do rendering on both ends, i.e. on the server and the client.

When a route is requested for the first time, the server shall do the rendering (mainly due to performance reasons). After that, all following actions shall result in client-side rendering.

This means that I must be able to render any page on the client and on the server, both times in the perfectly same way. Both ends have to support the same kind of routes.

How could I accomplish this task?

At the moment, I have taken a look at AirBnb's rendr project, but this definitely ties me to Backbone.js (I'm not sure if I want to stick with Backbone.js for all times), and seems to be not perfectly finished yet. At least, AirBnb does not recommend it for production use yet.

Any other ideas on how to do this?

As a sub-question I might also ask: What is the preferred way to share JavaScript code between the server and the client? For this, I also know piler, but I could imagine that there may be better solutions available.

Any hints?

like image 305
Golo Roden Avatar asked Jul 31 '13 16:07

Golo Roden


1 Answers

Well, I am building an application that does this. If you don't want to use rendr, you will have to code your own versions of some of the things they take care of. AFAIK at the moment your choices are rendr or home-grown. Here's some misc tips.

  • We use cheerio for server-side DOM operations, so when views render on the server, this.$el is a cheerio element instance. In the browser, it's jQuery.
  • You don't need event delegation and binding on the server side. Our code technically does this at the moment, but it's pointless and a cleaner solution would avoid it on the server
  • Once you have server-rendered HTML in the browser, you need a way to wire up a big nested tree of view instances to their corresponding elements in the big nested DOM tree. We have a home-grown solution for this, but Backbone.View.setElement is the core and you'll need to write some code to make this happen
  • We are re-rendering on the browser at the moment although there's probably a slicker way to take a view instance, give it some options in the constructor including a pre-rendered DOM node, and get things properly wired up without re-rendering. That's an exercise for the reader though. :-)
  • We also send down the raw data we need as JSON within a <script> tag so we have both server-rendered HTML (for perceived performance) and the raw data available as JSON so we can get our backbone models and views instantiated and operational. Again, you'll have to come up with some code to manage this situation.
  • We use browserify to bundle and share code between server and browser. All of our JavaScript is coded as CommonJS modules.
  • We have a basic isBrowser() function in our view parent class so we know when browser-only code should run for event bindings, etc.

Anyway, for what it's worth, after working this way for many months, I don't think backbone works well with this paradigm. Many of the core concepts from backbone are fine, but it doesn't lend itself to mapping view instances to pre-rendered DOM nodes. Bootstrapping models and collections from JSON is easier, but the view layer probably needs a significant fork to operate cleanly in this style.

like image 68
Peter Lyons Avatar answered Nov 03 '22 18:11

Peter Lyons