We're currently kicking off our first Backbone.js project here at work. In fact it's our first major JavaScript project apart from the odd jQuery stuff.
Anyway, we struggle with the architecture for our stuff. What is the best way to sort stuff out?
We've started with having everything in separate files broken up in folders for; views, models, collections and routers and then we include everything in our index.html
. The issue, though, is that this leaves us with having to check for the document ready event in every file. Is this the best way to do it?
Here's an example:
This is the file called PageModel
, the first line seems wrong...
$(function(){
app.models.Page = Backbone.Model.extend({
//stuff
});
});
Then in our index.html
we have:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ".dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
<link href="assets/css/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
var app = app || {};
app.models = app.models || {};
app.collections = app.collections || {};
app.views = app.views || {};
app.routers = app.collections || {};
app.templates = app.templates || {};
app.models.griditems = app.models.griditems || {};
app.views.griditems = app.views.griditems || {};
</script>
<script src=".6.2/jquery.min.js" type="text/javascript"></script>
<script src="assets/js/libs/json2.js" type="text/javascript"></script>
<script src="assets/js/libs/underscore-1.1.7.min.js" type="text/javascript"></script>
<script src="assets/js/libs/backbone-0.5.3.min.js" type="text/javascript"></script>
<script src="assets/js/models/GridItemModel.js" type="text/javascript"></script>
<script src="assets/js/models/GalleryGridItemModel.js" type="text/javascript"></script>
<script src="assets/js/models/NewsGridItemModel.js" type="text/javascript"></script>
<script src="assets/js/models/VideoGridItemModel.js" type="text/javascript"></script>
<script src="assets/js/collections/GridCollection.js" type="text/javascript"></script>
<script src="assets/js/templates/Submenu.js" type="text/javascript"></script>
<script src="assets/js/templates/GalleryGridItemTemplate.js" type="text/javascript"></script>
<script src="assets/js/views/GridView.js" type="text/javascript"></script>
<script src="assets/js/views/GridItemView.js" type="text/javascript"></script>
<script src="assets/js/views/GalleryGridItemView.js" type="text/javascript"></script>
<script src="assets/js/views/VideoGridItemView.js" type="text/javascript"></script>
<script src="assets/js/routers/Router.js" type="text/javascript"></script>
<script src="assets/js/Application.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
We're currently kicking off our first Backbone.js project here at work. In fact it's our first major JavaScript project apart from the odd jQuery stuff.
Anyway, we struggle with the architecture for our stuff. What is the best way to sort stuff out?
We've started with having everything in separate files broken up in folders for; views, models, collections and routers and then we include everything in our index.html
. The issue, though, is that this leaves us with having to check for the document ready event in every file. Is this the best way to do it?
Here's an example:
This is the file called PageModel
, the first line seems wrong...
$(function(){
app.models.Page = Backbone.Model.extend({
//stuff
});
});
Then in our index.html
we have:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
<link href="assets/css/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
var app = app || {};
app.models = app.models || {};
app.collections = app.collections || {};
app.views = app.views || {};
app.routers = app.collections || {};
app.templates = app.templates || {};
app.models.griditems = app.models.griditems || {};
app.views.griditems = app.views.griditems || {};
</script>
<script src="http://ajax.googleapis./ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<script src="assets/js/libs/json2.js" type="text/javascript"></script>
<script src="assets/js/libs/underscore-1.1.7.min.js" type="text/javascript"></script>
<script src="assets/js/libs/backbone-0.5.3.min.js" type="text/javascript"></script>
<script src="assets/js/models/GridItemModel.js" type="text/javascript"></script>
<script src="assets/js/models/GalleryGridItemModel.js" type="text/javascript"></script>
<script src="assets/js/models/NewsGridItemModel.js" type="text/javascript"></script>
<script src="assets/js/models/VideoGridItemModel.js" type="text/javascript"></script>
<script src="assets/js/collections/GridCollection.js" type="text/javascript"></script>
<script src="assets/js/templates/Submenu.js" type="text/javascript"></script>
<script src="assets/js/templates/GalleryGridItemTemplate.js" type="text/javascript"></script>
<script src="assets/js/views/GridView.js" type="text/javascript"></script>
<script src="assets/js/views/GridItemView.js" type="text/javascript"></script>
<script src="assets/js/views/GalleryGridItemView.js" type="text/javascript"></script>
<script src="assets/js/views/VideoGridItemView.js" type="text/javascript"></script>
<script src="assets/js/routers/Router.js" type="text/javascript"></script>
<script src="assets/js/Application.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
Share
Improve this question
edited Aug 19, 2011 at 8:32
Joel
asked Aug 19, 2011 at 7:53
JoelJoel
1912 silver badges6 bronze badges
1
-
There's no need to define your models / collection / views/ routers on the DOMReady event. The only thing that needs to be called only when the dom is ready is
Backbone.history.start()
. – shesek Commented Aug 19, 2011 at 9:38
2 Answers
Reset to default 4This is structure we use in our Backbone projects
<!-- Libs Section -->
<script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/jquery-1.5.2.min.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/jquery.validate.min.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/jquery.maskedinput-1.3.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/jquery.mousewheel.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/jquery.scrollpane.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/fileuploader.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/modernizr.min.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/json2.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/underscore-min.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/backbone-min.js")"></script>
<!-- Libs Section -->
<!-- Core Section -->
<script type="text/javascript" src="@Url.Content("~/Content/static/js/config.js")"></script> <!-- Global configs -->
<script type="text/javascript" src="@Url.Content("~/Content/static/js/core.js")"></script> <!-- Core methods for easier working with views, models and collections + additional useful utils -->
<script type="text/javascript" src="@Url.Content("~/Content/static/js/app.js")"></script> <!-- Application object inherites core.js as prototype -->
<script type="text/javascript" src="@Url.Content("~/Content/static/js/renisans.js")"></script> <!-- Project Object. Creates Namespace and Extends it with project specific methods -->
<!-- Core Section -->
<!-- Routers Section -->
<script type="text/javascript" src="@Url.Content("~/Content/static/js/routers/workspace.js")"></script>
<!-- Routers Section -->
<!-- Models Section -->
<script type="text/javascript" src="@Url.Content("~/Content/static/js/models/profile.js")"></script>
...
<!-- Models Section -->
<!-- Collections Section -->
<script type="text/javascript" src="@Url.Content("~/Content/static/js/collections/messages.js")"></script>
...
<!-- Collections Section -->
<!-- Views Section -->
<script type="text/javascript" src="@Url.Content("~/Content/static/js/views/workspace.js")"></script>
...
<!-- Views Section -->
<!-- Localization Section -->
<script type="text/javascript" src="@Url.Content("~/Content/static/js/localizations/ru_RU.js")"></script>
<!-- Localization Section -->
<!-- Init Section -->
<script type="text/javascript">
$(function() {
Rens.container = $('.l-wrapper'); // Some parameters
Rens.init({
Localization: LocalizationStrings || {}, // Object with localization strings
Profile: {
// Bootstraping initial data to Profile model
}
});
});
</script>
<!-- Init Section -->
content of app.js
var App = function() {
this.Views = {};
this.Routers = {};
this.Models = {};
this.Collections = {};
this.User = {};
this.router = null;
this.view = null;
this.baseLocation = null;
this.beforeInit = function() {};
this.afterInit = function() {};
this.init = function(initData) {
if (typeof(this.beforeInit) === 'function') {
this.beforeInit.apply(this, arguments);
}
if (this.Views.Workspace) {
this.view = new this.Views.Workspace();
}
this.baseLocation = window.location.href.replace(/[?#].*/, '') == Config.web.host;
if (this.Routers.Workspace) {
this.router = new this.Routers.Workspace(initData);
}
this.view && this.view.setListeners && this.view.setListeners();
Backbone.history.start();
if (typeof(this.afterInit) === 'function') {
this.afterInit.apply(this, arguments);
}
}.bind(this);
};
App.prototype = Core;
and content of renisans.js
var Rens = new App();
$.extend(Rens, {
container: null,
Error: function(data) {
// Handling error
},
Localization: function(dictionary) {
return {
get: function(name) {
var argumentsList = Array.prototype.slice.call(arguments),
strings = argumentsList.slice(1),
text = this[name];
if (text && strings.length) {
$(strings).each(function(i, string) {
var reg = new RegExp('\\$' + i, 'go');
text = text.replace(reg, string);
});
}
return text || 'SLB.Localization.' + name + ' not found!';
}.bind(dictionary)
}
},
formatDate: function(rawDate) {
var timestamp = /\d+/.exec(rawDate)[0],
date = Rens.DateUTC(timestamp),
months = Rens.Localization.get('months');
return {
date: date,
fullDate: [date.dd, months[date.mm], date.hh].join(' '),
shortDate: [date.dd, date.MM, date.hh].join('.')
};
},
beforeInit: function(initData) {
this.Localization = new this.Localization(initData.Localization);
}
});
also simplified content of models/profile.js
Rens.Models.Profile = Backbone.Model.extend({
...
});
If you are creating an application of this shape, i strongly suggest to use dynamic loading of your assets, like javascript and more.
you have several options for this:
- Require.js
- LABjs
- ...
i myself have no experience with LABjs, but i've been using Require.js in smaller projects for myself. But have yet to use it in a major project.
the advantages of such a system:
- you can work with dependancies, and your models or views will only be loaded when they are requested by another part of your code. not all at the beginning.
- require.js also provides features for minifying and agregating your code based on the dependancies you specified.
- require.js has a few small plugins for loading in text files (if you use a templating system this could be useful, or a plugin to define the order in which files need to be loaded.
- and require.js also has a special version for working together with jquery and its modules. (but you are not required to use this one, you can load in jquery trough manually as well)
you will need to wrap your models / views / ... in modules so require.js can load them dynamically. I asked about this here on stack overflow last week... you can find the info on how to do that here
I suggest you read the 'getting started with require.js' and see if you feel like using it.
because working with all models / views / ... in separate files is quite handy in development fase, but is defenately not remended when going into production. the fewer requests have to be sent by the browser to the server the better.