Skip to content

Modules with RequireJS

Béla Varga edited this page Jan 16, 2014 · 9 revisions

Table of Contents

Modules

Use an IIFE as simple module wrapper.

(function(global,undefined){
"use strict";

}(this));

Non Blocking JavaScript Loading

Simple non blocking file loader with the dynamic script tag trick.

var script = document.createElement("script");
script.src = "foo.js";
document.getElementsByTagName("head")[0].appendChild(script);

Maximum connections per Hostname

  • Because the browser can handle 6 - 24 Maximum connections per Hostname we should avoid to much requests.

Module Dependencies

If the files are loaded non blocking, we have no guarantee for the loading order. The same dependencies should e loaded only once.

Optimize and Merge JavaScript Files

When using require() in the top-level HTML page (or top-level script file that does not define a module), a configuration object can be passed as the first option

require.config({
    baseUrl: "/another/path",
    paths: {
        "some": "some/v1.0"
    },
    waitSeconds: 15
  });
define(id?, dependencies?, factory);

Using an ID is not recommended unless necessary.

define(dependencies?, factory);

Difference between define and reuqire:

define

  • loads dependencies
  • call the callback funtction

require

  • same steps like define
  • registers the return value from the callback function

moduleA.js

define( function(){
	var counter = 0;
	return {
		incrementCounter: function() {
			return ++counter;
		},
		resetCounter: function() {
			counter = 0;
			return counter;
		}
	};
});

app.js

require(["moduleA"], function(moduleA) {
	console.log(moduleA.incrementCounter());
	console.log(moduleA.resetCounter());
	console.log(moduleA.incrementCounter());
});
define(['moduleA'], function(moduleA) {
	return {
		incrementCounter: function() {
			return moduleA.incrementCounter();
		}
	};
});
define(['require'],function (require) {
	// inner require
	return require('moduleA');
});
define(['require'], function (require) {

	if(false){

		require(['moduleB'],function(moduleB){
			console.log('Module B');
			moduleB.incrementCounter();
		});

	} else {

		require(['moduleC'],function(moduleC){
			console.log('Module C');
			moduleC.incrementCounter();
		});

	}

});

moduleA.js

define(['require', 'jquery'], function (require, $) {

	var deferred = $.Deferred();

	require(['moduleB'],function(moduleB){
		deferred.resolve(moduleB);
	});

	return deferred.promise();

});

app.js

require(['moduleA'],function(deferred){
	deferred.done(function(moduleA) {
		moduleA.incrementCounter();
	});
});

moduleCore.js

define(function(){
	return {
		counter: 0
	};
});

moduleA.js

define(['moduleCore'], function(core){
	return {
		incrementCounter: function() {
			return ++core.counter;
		}
	};
});

moduleB.js

define(['moduleCore'], function(core){
	return {
		incrementCounter: function() {
			return ++core.counter;
		}
	};
});

app.js

require(["moduleA"], function(moduleA) {
	console.log(moduleA.incrementCounter());
});

require(["moduleB"], function(moduleB) {
	console.log(moduleB.incrementCounter());
});

moduleA.js

define(['moduleMediator'], function(mediator){
	mediator.subscribe('valueChange', function(msg){
		console.log(msg);
	});
});

moduleB.js

define(['moduleMediator'], function(mediator) {
	var counter = 0;
	return {
		incrementCounter: function() {
			mediator.publish('valueChange', ++counter);
		}
	};
});

moduleMediator.js

define(function(){
	"use strict";

	var channels = {};
	var mediator = {
		subscribe : function(channel, fn){
			if(!channels[channel]) channels[channel] = [];
			channels[channel].push({ callback : fn });
		},
		publish : function(channel){
			if(!channels[channel]) return false;
			for(var i = 0, l = channels[channel].length; i < l; i++){
				var subscription = channels[channel][i];
				subscription.callback(arguments[1]);
			}
		}
	};

	return mediator;

});

Common plugins:

  • text! : A text file dependency
  • domReady! : Cross browser domready solution
  • css! : Dynamically require css
  • order! : Force ordered evaluation

file.js

define({
	"foo"	: "red",
	"bar"	: "blue",
	"ninja"	: "invisible"
});

plugin.js

define({
	normalize: function (name, normalize) {
		return name;
	},
	load: function (name, req, load, config) {
		req([name], function (value) {
			load(value);
		});
	}
});

module.js

define(['plugin!file'], function (file) {
	return file;
});

single file build:

  • name
  • out

multi file:

  • modules
  • dir

module 1

js/lib/../common.js
----------------
js/lib/../common.js
js/lib/jquery.js
js/app/lib.js
js/app/controller/Base.js
js/app/model/Base.js

module 2

js/lib/../page1.js
----------------
js/lib/../page1.js
js/app/controller/c1.js
js/app/model/m1.js
js/app/main1.js

module 3

js/lib/../page2.js
----------------
js/lib/../page2.js
js/app/controller/c2.js
js/app/model/m2.js
js/app/main2.js