Organizing javascript code
Being JavaScript a scripting language, structure is one of the far most important concerns in large scale Javascript projects. It is important the parts of your application are well decoupled and 'self contained'. For an example, you may create your own UI components having its own template, logic, style, localizations, etc. in a single folder. Such self containment will let you organize your complex front end code in a manageable way.
Once you have your code organized, and self contained, there are other concerns that you need to address too.
- How should these loosely coupled components interact with out tight coupling
- How should I optimize these individual parts to load fast in my production env
I'm the author of BoilerplateJS reference architecture for large scale applications.
http://boilerplatejs.org
It incorporates most of the best practices discussed in Nicholas Zakas'presentation. You will find a sample implementation of a modular product suite in the code as well. Have a look, you will understand the concerns you will need to pay attention in doing a large scale application with JavaScript.
The single-best resource I've found on this subject is Addy Osmani's creative commons book, Patterns for Large-Scale JavaScript Application Architecture. It is based in part of Nicholas Zakas' Scalable JavaScript Application Architecture, adapting it to classic design patterns and a modern workflow.
Once you reach even a modest-level of complexity, you'll benefit from working with a framework built using a variation of the MVC architecture pattern. Backbone.js is the frontrunner and is a micro-framework, meaning it does less hand-holding than others. Other popular choices are Ember.js, KnockoutJS.
Extensions and boilerplates are also built on these frameworks to handle repetitive tasks such as data/model binding and scaffolding. For Backbone, check out Backbone.Marionette from Derick Bailey and Backbone Aura, a not-quite-ready-for-production adaptation of the Osmani/Zakas architectural model built using Backbone as its... well, backbone.
Let suppose we make cross platform application like below
Sorry for dirty content removing.
We want it cross platform so we write it with JavaScript. We want our syntax to be smart, elegant and laconic, so we use jQuery.
Our source structure will be like this
In js
folder we have three folders: controller
, model
, view
. We divide our application to three (can be many more) parts: main, menu and navbar.
For each of these parts we have ...Ctrl.js
and ...View.js
. We have only one model mainModel.js
(just in case).
Ctrl.js is where your handlers and where you attach them to controls. For example mainCtrl.js
:
app.mainCtrl = {
model: app.mainModel,
init: function(){
$('#addButton').click(function(){
this.model.addToFavorites();
});
$('#removeButton').click(function(){
this.model.removeFromFavorites();
});
}
};
(small stars on the right of the above screenshot are actually add/remove buttons )
Controller can hold references to both view and model or only to model (as in above example).
Model.js is where we update our backend and view. For example mainModel.js
:
app.mainModel = {
view: app.mainView,
all: {},
favorites: {},
init: function(){
/* for example
this.all = $.parseJSON ($.load('url'));
this.favorites = $.parseJSON ($.load('url'));
*/
this.showAll();
},
showAll: function(){
this.view.show(this.all);
},
showFavorites: function(){
this.view.show(this.favorites);
},
addToFavorites: function(item){
//add item to favorites
},
removeFromFavorites: function(item){
//remove item from favorites
}
};
View.js
is where we actually updates our view (by directly manipulating DOM). Methods of view can be called by related controller and/or model. For example mainView.js
:
app.mainView = {
show: function (items){
//create new element for each item
}
};
And finally we have app.js
file where we initialize our app:
var app = {
init: function(){
this.mainCtrl.init();
this.menuCtrl.init();
this.navbarCtrl.init();
this.mainModel.init();
this.navbarView.init();
}
};
We have only one global variable app
in our application. All views, controllers and models created inside app namespace.
And finally, finally is the order of import. You should import app.js
first as it defines app
variable.
<script src="vendor/js/jquery.min.js"/></script>
<script src="js/app.js"/></script>
<script src="js/controller/mainCtrl.js"></script>
<script src="js/controller/menuCtrl.js"></script>
<script src="js/controller/navbarCtrl.js"></script>
<script src="js/view/mainView.js"></script>
<script src="js/view/menuView.js"></script>
<script src="js/view/navbarView.js"></script>
<script src="js/model/mainModel.js"></script>
<script>
$(function(){
app.init();
});
</script>
</body>
</html>