Backbone provides us with a foundation to build the application. What it offers include:
-
models and collections
They encapsulate the business logic of the app and are in charge of the communication with the server. -
views
They can be regarded as the controller in MVC architecture which manages display, user interaction and change of model's state. This is where data binding is happening between view and model. -
events
Backbone Events is a robust messaging system for bridging the communications between various parts of the backbone components. -
router
It is a simple wrapper for HTML5 history API built on top of events.
With these features, one can easily build a moderately-sized and well-structured web app.
To build large scale web applications, more things need to be considered. But firstly, what is a large scale web application?
Addy Osmani writes here
In my view, large-scale JavaScript apps are non-trivial applications requiring significant developer effort to maintain, where most heavy lifting of data manipulation and display falls to the browser.
So to break it down, large scale application need to have the following traits.
-
it's an application
- software engineering
-
non-trivial
- large amount of development effort is needed
- long iteration of software cycles
- multiple developers involved
-
significant developer effort to maintain
- maintenance
- time and man power
- issue management (bug tracking)
-
most heavy lifting of data manipulation and display falls to the browser
- client needs to maintain complete states of a user session
- client needs to do most of the computations
- client needs to sync data with server occationally
In summary, if you are going to build some web app that most logics are happening on the client side, and it's going to be existed for a long time and you will be adding more and more features in the future, then you are building a large scale javascript application.
In this case, traditional software building practices come into the picture, i.e. various software patterns.
Addy mentioned quite a few important software patterns in his article, namely module, facade, mediator.
So before you start building your large scale javascript application, you need to think how to use those patterns to maximize the productivity gain and ease the maintenance efforts. Another nice name for this kind of thinking process: architecting.
Backbone itself isn't good enough for architecting. That's why when people compare it with AngularJS, they usually don't find more compelling to use the former.
MarioentteJS encompass quite a number of software patterns. It inherits the philosophy of Backbone. It's non opinionated. It's just a bunch of advanced handy tools at your disposal. Once you've master the skills of using them, they can do great things.
Okay, let's see what the tools are here.
Marionette.Application
Self-explanatory. It manages the namespaces, initializes the application, sets the initial regions and setups the message bus instance.
Marionette.ItemView, Marionette.CollectionView
These views extend from Backbone.View
. However, they have reduce the repetitive work that normally is required in creating a BackboneView for model
or collection
. And ItemView
can be used by collectionView
to instantiate subviews, this is just like the model
and collection
. Using them is more efficient than Backbone Views.
Marionette.Region
In Backbone development, there are normally 2 ways to create a view in the DOM. One is by specifying the tagName
and append the view's el
to the DOM. Another is to just specify the el
, so when the view is initialized, it's element is already in the DOM. The difference here is the former is like a removable view, appended/removed more than once. The latter normally stays for the lifetime of the application. In fact, the Region concept fit nicely for the latter. It's the virtual area that has a fixed width and position in the page. Its content can be swapped in and out with different views. Regions are mounted to application objects. However I believe ItemView
and Collection
view can also have Region
.
Marionette.AppRouter
This router is to be worked with controller. Marionette.Controller
is an object that initializes and manages views. The Controller and AppRouter are both to be declared inside a module.
Marionette.Controller
This is a neglected concept in Backbone. Controller is a facade object that manages the display and logics of the view object. In traditional Backbone project, many views can be combined together to form a particular function. The same piece of logics are spread in those Bacbkone Views. With a controller, those shared logics can be consolidated and the BacbkoneView will be solely responsible for the rendering. Moreover, a controller can interact with AppRouter to conveniently render the sub views.
Marionette.Module
It's a module system that help you to organize the code. It allows to write self contained code that can be tested. It is recommended to separate the application into smaller apps and contain each app inside a module. To start the module, just add a initialize function to the Application instance.
Here is an example of module.
Carpool.module("Content", function (Content, Carpool, Backbone, Marionette, $, _) {
Content.Router = Marionette.AppRouter.extend({
appRoutes: {
"listing/:id": "showListing"
}
});
var contl = {
showListing: function (id) {
console.log("show listing: "+id);
var listing = Carpool.request("entities:listing", id);
$.when(listing).done(function (data) {
var view = new Content.View({model:data})
Carpool.content_region.show(view);
});
}
};
Carpool.addInitializer(function () {
new Content.Router({
controller: contl
});
});
});
In Marionette, a request and response pattern has been implemented. It's the recommended way for controllers to communicate with models .
In Marionette, a lot more events are firing around than those in Backbone. For instance, when the application startup, it fires initialize:before
and initialize:after
. When a view is added to a region, it fires "region:add" event. Listening to these events can have a more granular control over objects.
Brian Mann in this video talked about architecting Backbone application using MarionetteJS. Watched the video after studying the Marionette project will be extremely helpful.
The proposed folder structure for Marionette project is like this:
-- app.js
-- apps/
|--app1/
|-- app1_controller.js
|-- list_view/
|-- form_view/
|--app2/
|--app3/
-- base/
-- components/
-- configs/
-- mixins/
-- entities/
-- vendor/
-- test
I personally find it very well structured. Whenever a new feature is to be added, we can create a new app module for that feature in the apps folder, just follow the pattern of other existing apps.
To wrap up, Marionette is definitely an indispensible tool for Backbone developers. By following its patterns and best practices, we can build large apps with a peace of mind.