If you have spent any time looking at Backbone.js, like many others, you are probably amazed by how lightweight, flexible and elegant it is. Backbone.js is incredibly powerful, but not prescriptive in how it should be used. With great power comes great responsibility, and if you’ve tried to use Backbone.js for a large project you might be asking yourself: how do I organize my code?
When thinking about “code organization” the questions you might be asking are:
- How do I declare and invoke Backbone types?
- How do I manage a separation of concerns?
- How do I define a clear entry point to my application?
- How do I pick a clear and consistent pattern to organize the code on the file system?
- How do I actually name my models, collections, views and routers?
All good questions! Is there an accepted answer? Nope.
There’s been a lot of debate about this issue in the Backbone.js community for several reasons. First, JavaScript, unlike Java or C, does not have inherent code organization mechanisms such as modules, namespaces or packages, leaving it up to each developer to sort it out for themselves. Second, it’s a complex problem that does not warrant a universal solution. All applications are not created equal and the reality is that the answer probably consists of a collection of patterns that can be used as necessary given the situation. At the end of the day the goal should be to create a code-base that is easy to understand, implement and maintain.
Having said all this, let’s dive into some of the details. First, you need to put your files somewhere on your file system. The physical layout is an important question often overlooked, but the days of “all code in a single file” are over, folks.
Here’s how you might layout your application structure:
.
├── assets
│ ├── css
│ │ └── main.css
│ ├── images
│ │ └── header.gif
│ └── js
│ └── libs
│ ├── backbone.js
│ ├── jquery.js
│ └── underscore.js
├── index.html
└── src
├── application.js
└── modules
├── friend.js
└── message.js
Static Assets
Your static assets such as CSS, images and JavaScript libraries required by your code should go under a parent directory, such as the assets directory in our example above. Separating your library code from your actual application code is an important step – it ensures everyone agrees on the baseline and dependencies and it prevents unintentional modifications to library code.
Application code
Your application code should be under its own directory, such as a src
directory. To enable a single point of entry, you should have a single file responsible for initializing the application (perhaps firing on DOM ready?) That file may also contain utility and helper methods, or those may live in their own util.js or helper.js respectively.
The rest of your application code should be divided into modules that can live under their own modules
directory.
A module is an encapsulated group of structures (for the purposes of our post, Backbone structures) that work cohesively
to provide a subset of functionality in your application.
Index.html
Your index file should import libraries in the following order:
- Third party libraries included in their dependency order (e.g., Backbone.js requires Underscore.js to already be loaded)
- Your application.js file which is the entry point for your application.
- Your application supporting files, like your modules.
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Example</title>
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body>
<div id="content">
<!-- ALL YOUR CONTENT HERE -->
</div>
<!-- Third-Party Libraries (Order matters) -->
<script src="/assets/js/libs/jquery.js"></script>
<script src="/assets/js/libs/underscore.js"></script>
<script src="/assets/js/libs/backbone.js"></script>
<!-- Application core (Order matters) -->
<script src="/lib/application.js"></script>
<!-- Modules (Order does not matter) -->
<script src="/lib/modules/friend.js"></script>
<script src="/lib/modules/message.js"></script>
</body>
</html>
Application.js
Your Application.js has several important roles. It serves as the entry point for your application by doing the following three things:
It defines the namespace of your application. For example, if your chat client application is called FireTalkChat, your namespace might be
chat
. All your application source should live under chat to prevent any collisions with other libraries.When referencing a module anywhere in your code, you need to make sure that those references all point to a single shared object. There are several ways to do that:
First, a namespace object can be created underneath which each property serves as a “module”.
naive.js
var chat = {
friend: { Views: {} },
message: { Views: {} }
};
While this method works (and is the simplest way to start organizing your code,) there are several drawbacks to this approach. Each time a new module is added, the original “namespace” object needs to be updated with a new property. Additionally, the initialization is repetitive in this case, especially if we know each of our modules should have the same base structure. Lastly and most importantly, calling chat.friend = null
, will obliterate your friend module. While modules should be in a mutable state, they should not be exposed in a way that will allow for their overwriting.
To address these issues you can create a reusable function that can retrieve the shared object reference when called. This function will create the shared object and “remember” it internally in connection with a key. This technique is called Memoizing. This way, every subsequent call will return the same object. By creating a closure around the module’s objects, you guarantee that it can’t be tampered with, and create a private scope for your module where you can define module-specific data.
application_module.js
var chat = {
// Create this closure to contain the cached modules
module: function() {
// Internal module cache.
var modules = {};
// Create a new module reference scaffold or load an
// existing module.
return function(name) {
// If this module has already been created, return it.
if (modules[name]) {
return modules[name];
}
// Create a module and save it under this name
return modules[name] = { Views: {} };
};
}()
};
3. Last but not least, this file defines the DOM ready callback. Once all the scripts are loaded, this function will execute and can initialize your application.
application_ready.js
// Using the jQuery ready event is excellent for ensuring all
// code has been downloaded and evaluated and is ready to be
// initialized. Treat this as your single entry point into the
// application.
jQuery(function($) {
// Initialize your application here.
});
Adding Your Modules
After having written your application.js, you’re ready to begin writing your modules. The modules should be named in a way that describes their intended purpose, for example:
- A friend module
- Model (a single friend object)
- Collection (a collection of friends
- Views:
- Quick (a single rendering of the friend)
- Detail (perhaps another view for the same model that shows more detail)
- List (a buddy list rendering)
- Router (a group of routes specific to the friend module)
- a message module may contain:
- Model (a single message object)
- Collection (of messages)
- Views:
- Message (of a single message)
- List (of a collection of messages)
- Routes (a group of routes specific to the messages)
When asking yourself whether to create single or multiple files to contain your modules, keep in mind that for development purposes, having multiple files is cleaner. However, that requires paying special attention to load order and having a build tool that can combine all the files for your production environment as downloading many files can bottleneck a page load.
Defining your module using the above memoizing technique requires the following steps:
- Create an immediately invoked function expression (IIFE) to create a module-specific scope:
friend_shell.js
// src/modules/friend.js
// Module reference argument, assigned at the bottom
(function(chat, Friend) {
//...
})(chat, chat.module("friend"));
- Define your dependencies at the top of the module, so that they are all grouped in a single location. Make sure to include the script tags for any dependencies before the script tag of the module that requires them. This is also a good opportunity to shorthand any application references that would be long otherwise.
friend_shell_deps.js
// src/modules/friend.js
// Module reference argument, assigned at the bottom
(function(chat, Friend) {
// Dependencies
var Message = chat.module("message");
// Shorthands
// The application container
var app = chat.app;
})(chat, chat.module("friend"));
3.Define the Backbone structures contained within your module. Note that you shouldn’t use the “new” keyword when referencing other modules as they might not have loaded yet. Save all the code that must run on page load for the jQuery ready function in your application.js.
friend.js
// src/modules/friend.js
// Module reference argument, assigned at the bottom
(function(chat, Friend) {
// Dependencies
var Message = chat.module("message");
// Define a friend
Friend.Model = Backbone.Model.extend({
initialize: function() {
// Add a nested messages collection
this.set({ messages: new Message.List() });
}
});
// Define a friend list
Friend.List = Backbone.Collection.extend({
model: Friend.Model
});
})(chat, chat.module("friend"));
message.js
// modules/message.js
// Module reference argument, assigned at the bottom
(function(chat, Message) {
Message.Model = Backbone.Model.extend({
defaults: {
unread: true
}
});
Message.List = Backbone.Collection.extend({
model: Message.Model
});
})(chat, chat.module("message"));
While there are many approaches to this, we found this to be a useful set of guidelines to work within. Given that the conversation about organizing your Backbone.js code is flourishing in the community, we’d love to hear your thoughts about this approach.
This post focused on the foundations of code organization, but given Backbone’s flexible nature, there are many best-practices we could tackle, such as build process, subrouting, stubbing etc. Stay tuned for additional posts and if you are interested in diving deeper, find out more about our “Building Web Applications with Backbone.js” training here: https://bocoup.com/education/classes/building-web-applications-with-backbone/
Comments
We moved off of Disqus for data privacy and consent concerns, and are currently searching for a new commenting tool.
Underscore has a memoize function built in, FYI! 🙂 http://documentcloud.github…
This works perfectly with memoize:
App = {\trun: function() {\t\tnew App.Router();\t},\tmodule: _.memoize(function(module) {\t\treturn App.module[module]||{Views:{}}\t})}
Also, take a look at this small Backbone Module Manager system I wrote. It’s pretty small when minified, and gives you a pretty sweet syntax for creating modules.
Maybe someone would be interested: we’re developing a open-source system like this: http://brunchwithcoffee.com.
The system provides:
– Nice directory structure — models, views, templates, styles, controllers, vendor things etc.
– Backbone, underscore, jquery as a default libraries
– Eco templates auto-compiling
– CoffeeScript support
– Testing support (Jasmine)
and much more. There are some issues left on github (feature / plugin requests like SASS / Jade templates / Batman.js support) — https://github.com/brunch/b… — but they’ll be fixed soon.
I think this is a really great introduction to how to organize larger applications. Something that has been difficult to find concrete info about in the past.
I would recommend in addition to this utilizing something like http://requirejs.org/. You could implement everything you are doing here but without having to worry about the actual \”setup.\” You can easily create modules that have their dependencies available to them within closed scope.
Additionally, you get a built in optimizer to concat all your files together for deployment.
I think this is the first step to understanding how organizing your project can work. The next step is to start integrating it into a larger build/organization process, perhaps with the help of something like RequireJS.
Great post Tim and Irene.
Absolutely Alex! We created this infrastructure with an open mind that was willing to accept that not every developer sees a module/script loading system the same way. The way this content was presented gets a developer on the right track mindset to making eloquent decisions.
We are discussing a follow up post which would take the feedback from the community to provide examples in popular loaders/module systems and any corrections.
WAT. Why not use a CommonJS AMD loader?
Well, that comment was a little flippant, apologies, guys.
Your intent in advocating modularization is admirable and the project structure you suggest is solid, but manual dependency management doesn’t scale beyond small projects. Please consider updating with a link to an implementation of the CommonJS AMD standard. RequireJS would be an excellent choice.
Trust me: the road that starts with ‘include the script tags for any dependencies before the script tag of the module that requires them’ soon takes a sharp left turn toward Madness, USA.
Lon, loaders can coexist with our implementation. In fact how we describe the fundamental organization layout here, works perfect with something like RequireJS.
Personally I’m not a fan of script loaders, but I am also not a fan of forcing an opinion. Ensure proper organization and pick the right tools to facilitate it.
As I said, I think your project organization is solid. It’s clean and orthogonal and well thought out. That’s not what I have an issue with.
I think part of the confusion here is that RequireJS really serves two purposes:
1) script loading: it asynchronously loads scripts on demand
2) dependency management: it figures out the dependency graph of your project and resolves dependencies automatically when you require a module
The first purpose is irrelevant here. I really only use it in development, myself. When I deploy, I run the build tool for whatever dependency manager I’m using and push out a single concatenated file.
The second purpose is the one at issue. Your post suggests a mechanism for specifying and resolving module dependencies. That mechanism is only compatible with RequireJS in the trivial sense that you don’t step on any of its global names, so they can both run in the same page. Your module loader doesn’t know anything about the dependency graph, so you have to build one by hand by carefully ordering your script tags in the page.
I can assure you from experience that building a dependency graph by hand does not scale beyond small projects. It’s hard to reason about, tedious to manage and brittle. We have better tools now and we should use them.
Another problem is that there’s a spec for this, and you’re not implementing it. That can be ok if there’s a good reason that the spec won’t work for you, but in that case you have a responsibility to explain those reasons. The burden of proof is pretty high.
Let me be clear that I applaud y’all for giving a clear, well-written and cogent argument for modular and clean organization of code. Our community needs more people like y’all: people who champion good engineering over expediency.
It’s just a shame to perpetuate obsolete and deprecated practices while you’re at it.
This is an old comment, but I’ll try anyways. Are you saying that not using requireJS for dependencies is deprecated? Second, what do you mean when you are talking about the spec? How should this be handled? How can this affect an application?
Hi Lon,
Thanks for taking the time to write your thoughts. We appreciate your point of view but wanted to call out a few issues and inconsistencies with our actual post:
1. As we said, this is a foundational introduction to the concept of modularizing. We are by no means claiming it’s the only way to go and we are clearly indicating that downloading many script files is bad in production. There’s room for posts that optimize your script loading and there’s room for post that talk about what those scripts should be.
2. The way our module function works actually allows you to reference any module regardless of its load order because the memoizing function will always amend a shared object. As long as all your initializations kick off on dom ready, load order doesn’t actually matter. The load order we were talking about had to do with dependency libraries such as jQuery & Backbone.
3. CommonJS is not a finalized specification and it is an unofficial proposal. We take specifications very seriously here and are looking forward to seeing whether the spec will actually be accepted by the larger community and become a standard.
4. In CommonJS you still have to define what each module’s dependancies are, the \”dependency graph\” is then based on your definitions. Using our method, the load order doesn’t matter, so that solves that problem.
In the end of the day, nothing is preventing you from taking our files and using a script loader to handle their loading. This post is meant to address a level way before thinking about script loading.
For more thoughts about script loading, this is a pretty great conversation to reference:
https://github.com/pauliris…
This is super helpful. It’s a nice milestone for developers who have just passed through Backboneopolis and are looking for the next step. I’m doing my best to avoid script loaders, as they actually seem to add unnecessary opacity and… further systems of dependency.
Thanks for the article and striking up the discussion around structure etc.
I’m currently writing my first large Backbone App and plan to follow a similar pattern to this as a learning process before moving onto something that will get more traffic which will use Require and Backbone. It’s great to see I’m on the right path and that there is content out there to help me along.
Is there any advantage to passing in the module to the anonymous function instead of just declaring it in the same way you do with dependencies?
(function() {
// Initialize module
var Friend = chat.module(\”friend\”);
// Dependencies
var Message = chat.module(\”message\”);
})();
Doing it this way seem to make it a bit cleaner as you don’t have to go to the bottom of the file to see what has been passed in.
Scott Harvey
If you’re bundling up jquery, requirejs, and backbone, I would suggest to look at the YUI 3.4: they have all the dom manipulation tools you need, some nice widgets, an App framework with Model, ModelList, View and Controller, an async loader with dependencies resolver (with a combo server too), an already tested and proved module system, some build tools, some tools to manage classes, extensions, mixins, plugins. Not least: good documentation, nice community, a big company backing up, a yearly conference (YUIConf 2011 is in the first days of November), regular online meetups with Q&A sessions. And one last thing: it can run on node.js.
Scott Harvey,
They are absolutely equivalent. Do whichever way looks best to you =)
as a new user to real javascript programming this is a very nice article on organising your code. Many thanks for that, because information on this is not that widespread, especially not such a well written article like this :).
i already said i’m quite new to javascript, and backbone…
but am trying to wrap my head around this new way of working. It does not help that this is also my first real progress in the world of MVC (or equivalent patterns)
so here i would like to pose a question about more advanced things than just a message and a friend. let’s say we build an app, that heavily combines two modules on one view, to stick with the friends and messages since you already have those modules explained above, we make a view with a grid of friends and messages and the grid holds data on who commented on what or something, just picture the grid.
where does that view go, you can’t really add it in the friend module, as it relies so much on the messages, and the other way around.
does it need it’s own module then?
In my experience RequireJS is really the way to go, for the following reasons:
1. Automatic Module load order
2. Dynamic module loading (after page load)
3. Build tool included
– it only includes the modules needed by recursively tracing the dependencies of a single module (ex. your app module)
Unless i missed something, the approach in this article really requires all modules to be loaded on page load… Although load order doesn’t need to specified, I would still need to maintain a list of all my dependencies. Which is slightly better than nothing, but problem avoided with RequireJS 🙂
BTW- requirejs doesnt use commonjs but AMD as a spec.
BTW2- a module form translatable from AMD modules is planned for the next version of ecmascript. (see the work by David Herman)
Hey Peter,
We addressed most of what you said already in the comments… \u00a0No where are we advocating to *not* use RequireJS. \u00a0This is a foundational post that seeks to enlighten new Backbone.js developers to use modular practices.
We show loading modules individually in this post, but that was only because it will take another post’s worth of content to properly describe a build technique.
You are confusing CommonJS and AMD as if they are comparable terms. \u00a0They are not. \u00a0See:\u00a0http://wiki.commonjs.org/wi…
Hi Tim! are you planning to bring us some Posts how to use the Backbone Boilerplate including require.js??
Thanks a lot for the work!
Hey Sander,
Sorry for the late response. This question is very common in MVC architectures, and the traditional response is to create a separate module that contains the view that you require. You may find that this grid exists in a larger module, like dashboard or something similar.
Assembling the modules into that view would occur inside a route callback.
Loving this structure, seems really well thought through!
Can you suggest the best method to init the whole app? Should every module have it’s own contained init() function with each init functions being called from the master application init function $(function(){}) ?
Here is modular Backbone.js implemented with AMD/Require.js
Clean Globals and Great Compilation
http://backbonetutorials.co…
Links back to this page in the footer
Ah, thanks for that link. I fumbled my way through this on my own a couple of months ago, probably just before that guide was published from the looks of it. RequireJS/AMD was a little tricky to make sense of to me, so this is a nice reference to refer others to.
I don’t no
Would it be possible to get a few lines of example code that would go here;
// Initialize your application here.
Perhaps something like:
jQuery(function($) {
\u00a0 // Create the root application Router
\u00a0 var Router = Backbone.Router.extend({ … });
\u00a0 // Initialize it into the application namespace
\u00a0 app.router = new Router();
\u00a0 // Start tracking history
\u00a0 Backbone.history.start();
});
Ahh! it burns us! Please do remove the image background! 😉
I found your approach interesting but had a following problem implementing it.
I defined my App.module exactly as you wrote and now, when I tried to create new collection with:
var c = new App.module(‘moduleName’).Collection();
(i defined Collection = Backbone.Collection.extend({…}) inside its module)
i get:\u00a0TypeError: Cannot read property ‘bind’ of undefined
You should first load the module, and only then reference it.
var ModuleName = App.module(‘moduleName’);
var c = new ModuleName.Collection();
Though I don’t know why is that
did you try:
var c = new (App.module(‘moduleName’).Collection)();
Vegnus, did you change index.hmtl to reference the application.js and module JavaScript in /src instead of /lib?
Vegnus, did you replace \”/lib/\” with \”/src/\” in the index.html script tags that load application.js and the module JavaScript?
hey,
great stuff, thank you so much for this! could you also provide a little snippet for Backbone.View inside a module? the thing is…\u00a0
I tried to add inside a module:
MyModule.Views.Main = Backbone.View.Extend({bla… });
then in my main.js
var myMod = App.module(‘mymodule’);
var myView = new myMod.Views.Main();
but always get a typeerror undefined for Main. I tried to play a bit with names and return of \”module: function()\” with no success so far… would you pls provide a little example?
[EDIT] ok, found the problem: assigning a template in a view with the method commonly found in the examples { template: _.template( $(‘#something’).html() ) } gives an error, underscore complains because the dom is not ready and cannot replace null values. so I guess I need to find a way of loading templates asynchronously?
cheers
Can you remove that twitter bar on the right? It’s totally unrelated to the article and detracts from its content.
First off let me start by saying I never comment on these things…. I normally just digest the information, silently thank the writer and move on with what ever I am trying to do at the time.
However, for someone that is getting out of doing stuff with restful php, and ajaxy type methods, into this javascript app life. This guide was a god send, you have completely cleared up so many foggy zones that you have no idea!
Thank you for taking the time to express this information so cleanly!\u00a0
I will be taking the time to create a dreamweaver project template and page templates for this project lay out, and will email you the download link if you wish to post it then do so!\u00a0
Thanks again!
How do we create views and run them on jquery load event using this approach ? Currently I need to declare my module within the jquery load function:
$(function() {
});
This way I have to declare my module views OUTSIDE the module file itself, this is not good, at least the way I see it.
Cheers
I started using a universal singleton for my app. \u00a0This is the only file (besides require.js) that I hard-load using a <script> tag. \u00a0All my other scripts register themselves with the singleton on init. \u00a0Other special exception is the \”auth\” object which I built into the app singleton, appropriate for applications that depend primarily on being logged in as a specific user.
var app = {\u00a0 \u00a0 // Create this closure to contain the cached modules\u00a0 \u00a0 auth:{},\u00a0 \u00a0 __modules:{},\u00a0 \u00a0 get:function (name) {\u00a0 \u00a0 \u00a0 \u00a0 if (this.__modules[name])\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return this.__modules[name];\u00a0 \u00a0 \u00a0 \u00a0 else\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return null;\u00a0 \u00a0 },\u00a0 \u00a0 set:function (name, value) {\u00a0 \u00a0 \u00a0 \u00a0 if (!this.__modules[name])\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 this.__modules[name] = value;\u00a0 \u00a0 \u00a0 \u00a0 return this.__modules[name];\u00a0 \u00a0 }};
var app = {
auth:{},
__modules:{},
get:function (name) {
if (this.__modules[name])
return this.__modules[name];
else
return null;
},
set:function (name, value) {
if (!this.__modules[name])
this.__modules[name] = value;
return this.__modules[name];
}
};
Merci beaucoup… 😀
wonderful tutorial…love your structural approach. btw, you confused /lib/ in index.html with /src/ that you are using in your graphical filetree
I almost never comment, but had to here. Great post! I wish others distilled information as well as this has been done… Specific enough to provide strong guidance but defining the areas that could be \”gray\”. Excellent post!
Nice Post !!!
Thanks for this. A couple of things I don’t understand.
One of your examples includes this line: `var app = chat.app;` What is `chat.app`? I can’t see it referred to anywhere else.
Second, I don’t follow how or where you would add Views to your module. At the moment an empty dictionary called `Views` is created for each module. Why? Where do the Views to go in here come from?
I also got the same problem. How can I pass module properties that are updated by the modules?
You’re right that was overlooked that in the tutorial, basically your app should be initialized as an object with anything you want to init with like extending backbone events with the initial module memoization stuff like so:
var chat = {
module: function() {
…
}(),
app: _.extend({},Backbone.Events)
};
I think the very last link mentioning training should point here http://training.bocoup.com/… instead of where it points now
dunno
I have some views such as dialog, loader. Should I declare them as modules too? I have an object named `Views` under my custom namespace but I do not like this approach. Any ides about it? Thanks!
This confusing as shit
agreed, I’ve just looked at 10+ backbone.js tutorials and I still don’t fully understand it