<script src="jquery.js"></script>
<script src="jquery.easing.js"></script>
<script src="slideshow.js"></script>
...
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-12345678-1']);
</script>
We know that JavaScript tags block page rendering
Not every JavaScript file is needed when the page first loads
Multi-page applications start copying & pasting script tags
As the site grows, so does complexity
No encapsulation of export of value = namespace pollution
(function () {
var $ = this.jQuery;
var slideshow = $('#id').slideme();
this.myExample = function () {};
}());
define(['widget'], function (Widget) {
return Widget.extend({
"method" : function () {
...
}
});
});
Modules are encapsulated and sand-boxed
Create and reuse code from different products
Structured, clean code base
Async loading, managed dependencies
Lazy load modules (stuff not used by the user yet can be loaded in background when needed on demand)
Not a technology, but a specification proposal
// naming you module is optional, and in fact, you should avoid it
// naming your modules makes your code less portable
// dependencies listed in an array, same rules as require()
// mapped to arguments in the callback
define('name', ['dependency', 'bar'], function(dependency, bar) {
// Export the interface for our module.
return {
win: dependency.win,
lose: bar.lose
};
});
define(['dependency', 'bar'], function(dependency, bar) {
// Export the interface for our module.
return {
win: dependency.win,
lose: bar.lose
};
});
define(function() {
// Export the interface for our module.
return function(){
//functions can exported to!
};
});
// foo is an external module
// foo can be a path or an alias to a path using require configuration
// the exports or return of foo will be mapped
// to the corresponding argument.
require(['foo'], function(foo) {
foo.win()
});
// Multiple dependencies
require(['foo', 'bar'], function(foo, bar) {
foo.win();
bar.lose();
});
// Dynamic loading of dependencies
define(['require', 'jquery'], function(require, $) {
// lots of awesome code
$('#chat-start').on('click', function(){
// dependencies are paths so this will grab features/chat.js
require(['features/chat'], function(chat) {
chat.start();
});
});
return //awesome api;
});
// multiple loaders!
var reqOne = require.config({
context: "version1",
baseUrl: "version1"
});
require.config({
baseUrl: '/js',
paths: {
// ;-)
'underscore': 'lodash'
}
});
require.config({
shim: {
'backbone': {
// These script dependencies should be loaded before
// loading backbone.js
deps: ['underscore', 'jquery'],
//Once loaded, use the global 'Backbone' as the
//module value.
exports: 'Backbone'
}
}
});
requirejs.config({
map: {
// When some/newmodule requires foo it gets the newer version.
'some/newmodule': {
'foo': 'foo1.2'
},
// When some/oldmodule requires foo it gets the older version.
'some/oldmodule': {
'foo': 'foo1.0'
}
}
});
// the <plugin>!<resource> is the syntax to use a plugin
// plugins are just modules that implement a specific api
define(['foo!bar'], function(bar) {
// Export the interface for our module.
});
define(['cs!module.coffee'], function(module) {
// module was compiled for me!
});
define([
'text!mytemplate.handlebars',
'handlebars'
], function(template, handlebars){
// template is just a string
return handlebars.compile(template);
});
write: function (pluginName, name, write) { ... },
load: function (name, parentRequire, load, config) {
// Require the intended dependency
parentRequire([name], function (val) {
// Add extra functionality
val.extra = function () { alert('extra!'); };
// resolve the dependency manually
load(val);
});
}
require(['plugin!module'], function (module) {
module.extra(); // alerts 'extra!'
});