6

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?

1

1 Answer 1

11

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.

Sign up to request clarification or add additional context in comments.

5 Comments

How did you do 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 ?
Have you considered using 'prerender'? (github.com/prerender/prerender) I was following your lead and stuck on the first step. I have an html that has javascript block in it. and everything starts from there. How do I execute the javascript in the script block from server side as a browser would do? I'm perplexed.. Can you shed a light please?
No, since my server side is node, the idea is to render the HTML in node without a server-side browser solution like phantomjs, which prerender uses. That's the "isomorphic" goal anyway. But most javascript code isn't isomorphic at the moment - you need to design your application to function in that style.
But can you please elaborate on the technique used to connect cheerio to Backbone instead of jQuery?
In our base view class's init method we set this.$el = cheerio("<div></div>");. I think that's essentially all there is to it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.