Building and managing large scale JavaScript applications becomes cumbersome as the size of application code grows. Developers often spend lot of time figuring out the flow of application instead doing the original task. There can be various reasons causing this but, it can be prevented by correctly implementing dependency management and organising the application code properly. In this article, we will try to address the two main issues in building large scale JS applications –
- Code Structuring (using Backbone.js)
- Dependency management(using RequireJS)
Backbone.js is a small JavaScript library (~ 6 kb) that allows programmers to structure your JS code by providing model, view, controller, and router classes. It is designed for the single page applications and can be customized as per the project needs. It also provides a pub-sub (publish-subscribe) mechanism to allow objects to trigger and bind the events.
RequireJS serves very different purpose than backbone.js. It provides ability to improve page performance by Asynchronous module Definition (AMD) mechanism and organize each module in single JavaScript file. The Asynchronous Module Definition (AMD) API specifies a mechanism for defining modules such that the module and its dependencies can be asynchronously loaded. This is particularly well suited for the browser environment where synchronous loading of modules incurs performance, usability, debugging, and cross-domain access problems.
The following section describes how to take advantage of Backbone.js, RequireJS to build a Ruby on Rails based application while using CoffeeScript syntax instead of Javascript to improve readability. It also points at some of the issues you would face and provides solutions for the same. Treat this as a step by step guide and refer to library documentation for more details.
The completed code and examples can be download from the github.
1. Create a new project
|
|
$ rails new backboneworld |
2. Add Gemfiles Backbone.js & RequireJS
|
|
gem 'backbone-on-rails' gem 'requirejs-rails' |
3. Creating the first controller
Create a home controller that will serve as home page for our sample-
|
|
$ rails generate controller home index |
4. Set the application home page
Tell Rails where your actual home page is located, edit routes.rb
|
|
Blog::Application.routes.draw do #... # You can have the root of your site routed with "root" # just remember to delete public/index.html. root :to => "home#index" |
5. Convert plain JavaScript to coffeescript syntax
CoffeeScript is a little language that compiles into JavaScript.
So let’s rename
app/assets/javascripts/application.js to application.coffee and add following code
|
|
define ['jquery'], ($) -> # Start up the app once the DOM is ready $ -> alert "The app has started with requirejs. yay!!" |
Still not clean?
, if you see console log, you see an error “Error: Module name ‘underscore’ has not been loaded yet for context: _”

Thanks to Noah [github] for providing a fix for this.
Update Gemfile as follows
|
|
gem 'requirejs-rails' , :git => 'https://github.com/coderanger/requirejs-rails.git' # See https://github.com/jwhitley/requirejs-rails/pull/59 |
Run bundle install and restart your application, everything is clean. Great!! it works now.

6. Building basic backbone app
We will try a very simple single page application example that creates a view. It also gets the username and creates a child view on the fly within javascript, no round trip to server. This only demonstrates the usage of Backbone.js Views. We will have a look at using Models, Collections, Routers in another blog.
Let’s add a placeholder application level container tag or div, where we will append the html generated from backbone views. In a single page application, the approach we follow is, have a container tag where the backbone view generated html is appended, and every user event or operation on web page either updates existing tags or appends/removes backbone views (html).
Edit
application.html.erb with
|
|
<body> <!-- add placeholder application level container --> <div id="TheApp"> </div> ... |
7. Remove home.html.erb
First create following folders for backbone,
app/assets/javascript/models, app/assets/javascript/views, app/assets/javascript/collections where we can write the backbone views, models, collections.
Move home.js.coffee to
app/assets/javascript/views folder and write a basic view.
Backbone can use templates to render views, for now just add following template in home.coffee.
|
|
<div style="margin: 150px 0 0 150px"> <p> Hello from an Backbone app.</p> </div> |
Here is a view using above template. Note that templates can be moved to separate files which help in better maintaining the application.
|
|
# Contents of home.js.coffee define ['backbone'], (Backbone) -> class HomeView extends Backbone.View template: _.template("""<div style="margin: 150px 0 0 150px"> <p> Hello from an Backbone app.</p> </div>""") render: -> # Load the compiled HTML into the Backbone "el" @$el.html( @template() ); |
Here you see that Backbone view is used to render the text ” Hello from an Backbone app.”
8. Adding event handling
Add following tags to current template. Here we will enable button when a user enters some text and handle the button click event.
|
|
<div style="margin: 150px 0 0 150px"> <p> Hello from an Backbone app.</p> <button id= "createview" type="button" disabled> Create a new Backbone view </button> <input id="username" type="text" value="Please enter your name..."> </input> <div id="child_view"> </div> </div> |
Add the event handlers to HomeView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
events: 'click input#username': 'clearInput' 'keyup input#username': 'editName' 'click button#createview': 'createView' # This creates and renders the child view on user input. clearInput: (evt) -> evt.preventDefault() @$(evt.currentTarget).val('') @$('#createview').attr('disabled', 'disabled') editName: (evt) -> evt.preventDefault() if @$('#username').val().length @$('#createview').removeAttr('disabled') else @$('#createview').attr('disabled', 'disabled') createView: (evt) -> evt.preventDefault() username = @$("#username").val() new ChildView({ el: $("#child_view") , username: username}) |
** Note here that we have created a new child view which appends itself inside the #child_view div within HomeView
Child view source
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
define ['backbone'], (Backbone) -> class ChildView extends Backbone.View template: _.template("""<div style="background-color: red"> <div> Hey <%= userName %>, you just created a new Backbone view</div> </div>""") initialize: -> @username = @options.username # Lets just render the view on creation. @render() render: -> variables = {userName: @username} # Load the compiled HTML into the Backbone "el" @$el.html( @template(variables) ); |
There you go, rerun your application and you can see that views is created on the fly.


9. Moving templates out from backbone views
Two options: add script tags ‘text/template’ in html, or move it the separate file.
Let’s look at first option. Let’s move the child view template to script tag in application.html.erb
Remove the tempate: _template… definition from Child view and add the following to application.html.erb
|
|
<script type="text/template" id="child_view_template"> <div style="background-color: red"> <div> Hey <%= userName %>, you just created a new Backbone child view</div> </div> </script> |
And update the child view render function as follows.
|
|
render: -> # Compile the template using underscore template = _.template( $("#child_view_template").html(), {username: @username} ) # Load the compiled HTML into the Backbone "el" @$el.html( template ); |
Run your app. It will fail with the following error.
Error:

Here you go the culprit is:
<div> Hey <%= userName %>, you just created a new Backbone child view</div>
The problem is that Underscore is using the same syntax for templating as ERB, so it is conflicting. You need to tell Underscore to use a different syntax.
Here is the fix – Update the script tag as follows:
|
|
<script type="text/template" id="child_view_template"> <div style="background-color: red"> <div> Hey {{= username }}, you just created a new Backbone child view</div> </div> </script> Update the application.coffee with: _.templateSettings = { interpolate : /\{\{=(.+?)\}\}/g, escape : /\{\{-(.+?)\}\}/g, evaluate: /\{\{(.+?)\}\}/g, } |
Rerun your application and you can see the application working with templates moved out from your backbone views.
This post is meant to be a hands-on tutorial with setting up projects using Backbone.js, RequireJS and rails. Feel free to fork the source for samples used in this post on github – https://github.com/ClogenyTechnologies/Rails-Backbone-RequireJS
INTERESTED?
If all of this is interesting/exciting to you, and you’d like to chat more about working with us, drop us a note; we’d love to hear from you.