jQuery Tween Scroller Demo
What?
Nowadays building any non-trivial JavaScript application requires a significant amount of code. Historically JavaScript doesn't have any modular system, which allows you to split your code in modules, separate files and control their dependencies. Moreover a big application doesn't need to initialize all its subsystems on start. Here a lazy loading of submodules (which is actually AMD) comes to help. There are a lot of great libraries that provide AMD functionality (RequireJS is the most notable). However, I feel a constant frustration with their complexity and strange design decisions. I feel that things are not DRY and my code is not narrative when I'm writing things like this in RequireJS:
requirejs(['jquery', 'canvas', 'app/sub'], function ($, canvas, sub) {
//jQuery, canvas and the app/sub module are loaded and can be used here now.
return {
helloWorld: function() {
console.log('Hi there!');
}
};
});
This is how I want it to be done in my code:
MyApp.define('Main', function(require, exports) {
var $ = require('jquery'),
canvas = require('canvas'),
sub = require('sub');
exports.helloWorld = function(){
console.log('Hi there');
};
});
Another issue of RequireJs is that a module structure mimics a filesystem structure. So rebasing a single file may become a significant pain in the ass. The most common process of building your scripts (e.g. with grunt) is:
Concat all JS files in the given directory into a single file, which is used at run time
Minify this file
With such approach, usage of the RequireJS may become really painful.
So if you want
nice, modular and narrative code
filesystem/URL-agnostic AMD library with nice error handling
concat all your scripts (without taking care of their order/filesystem path) into a single file
then mods is your choice.
Usage
1. Init your app/module container
var MyApp = new Mods();
2. Encapsulate used libs
MyApp.define('jQuery', function() {
this.exports = jQuery.noConflict();
});
MyApp.define('async', function() {
this.exports = async.noConflict();
});
3. Define your modules
//Use objects as exports...
//---------------------------------------------------------
MyApp.define('Greetings.Settings', function() {
this.exports = {
text: 'Hello world',
color: 'red'
};
});
//...or use functions as exports...
//----------------------------------------------------------
MyApp.define('Greetings.Printer.DOM', function(require) {
var $ = require('jQuery');
this.exports = function(text, color) {
$('')
.text(text)
.css({color: color})
.appendTo('body');
};
});
MyApp.define('Greetings.Printer.Console', function(require) {
this.exports = function(text) {
console.log(text);
};
});
//...or just extend exports object (like in node.js)
//----------------------------------------------------------
MyApp.define('Main', function(require, exports) {
var Settings = require('Greetings.Settings'),
printToDOM = require('Greetings.Printer.DOM'),
printToConsole = require('Greetings.Printer.Console');
exports.helloToDOM = function(){
printToDOM(Settings.text, Settings.color);