4. The Problem
Today’s complex Web Apps have created the
need for:
Structure
Some sort of framework, to aid in rapid development
5. The Problem
Today’s complex Web Apps have created the
need for:
Structure
Some sort of framework, to aid in rapid development
Object orientation
To “black box” complex code
6. The Problem
Today’s complex Web Apps have created the
need for:
Structure
Some sort of framework, to aid in rapid development
Object orientation
To “black box” complex code
Modules and packages
RE: The 2,500 best jQuery plugins...
7. The Problem
Today’s complex Web Apps have created the
need for:
Structure
Some sort of framework, to aid in rapid development
Object orientation
To “black box” complex code
Modules and packages
RE: The 2,500 best jQuery plugins...
Dependencies
(includes, requires, imports, what-ev)
8. The Problem
Today’s complex Web Apps have created the
need for:
Structure
Some sort of framework, to aid in rapid development
Object orientation
To “black box” complex code
Modules and packages
RE: The 2,500 best jQuery plugins...
Dependencies
(includes, requires, imports, what-ev)
Reusable code
Scope-isolated, clean API, portable
Globals are bad!
14. Single File - pros & cons
Pros
Fewer resources means faster load times.
15. Single File - pros & cons
Pros
Fewer resources means faster load times.
No “build step” necessary.
16. Single File - pros & cons
Pros
Fewer resources means faster load times.
No “build step” necessary.
Cons
Difficult to maintain and edit a file thousands of
lines long.
GOTO Line #
17. Single File - pros & cons
Pros
Fewer resources means faster load times.
No “build step” necessary.
Cons
Difficult to maintain and edit a file thousands of
lines long.
GOTO Line #
Code reusability is dirt poor.
Copy and paste?
18. Single File - pros & cons
Pros
Fewer resources means faster load times.
No “build step” necessary.
Cons
Difficult to maintain and edit a file thousands of
lines long.
GOTO Line #
Code reusability is dirt poor.
Copy and paste?
Makes team development near impossible.
GITMERGETOOL
20. Multiple Files
Multiple files which follow an object oriented or
namespaced approach are easier to maintain because
the brain more easily maps files to ideas.
21. Multiple Files
Multiple files which follow an object oriented or
namespaced approach are easier to maintain because
the brain more easily maps files to ideas.
[dom.js] [lang.js]
library.dom = { library.lang = {
// code // code
} }
[events.js] [string.js]
library.events = library.string =
{ {
// code // code
} }
23. Multi File - pros & cons
Pros
One-to-one, file-to-class makes organization
easier.
24. Multi File - pros & cons
Pros
One-to-one, file-to-class makes organization
easier.
The brain more easily maps files to concepts
(objects).
25. Multi File - pros & cons
Pros
One-to-one, file-to-class makes organization
easier.
The brain more easily maps files to concepts
(objects).
More team friendly.
26. Multi File - pros & cons
Pros
One-to-one, file-to-class makes organization
easier.
The brain more easily maps files to concepts
(objects).
More team friendly.
Cons
The files (and server requests) will add up fast and
that will slow down the page.
27. Multi File - pros & cons
Pros
One-to-one, file-to-class makes organization
easier.
The brain more easily maps files to concepts
(objects).
More team friendly.
Cons
The files (and server requests) will add up fast and
that will slow down the page.
Lots of <script> tags. BLEAH.
28. Multi File - pros & cons
Pros
One-to-one, file-to-class makes organization
easier.
The brain more easily maps files to concepts
(objects).
More team friendly.
Cons
The files (and server requests) will add up fast and
that will slow down the page.
Lots of <script> tags. BLEAH.
The system to track all these files and their order is
YOU.
36. Dependency Matters
Scripts load in this order
A change is made to dom.js
Adds events to node on create.
[dom.js]
[events.js]
library.dom = {
// code
[lang.js]
library.events =
}
{
[string.js]
library.lang = {
// code
} // code
} library.string =
{
// code
}
37. Dependency Matters
Scripts load in this order
A change is made to dom.js
Adds events to node on create.
[dom.js]
[events.js]
library.dom = {
// code
[lang.js]
library.events =
}
{
[string.js]
dom.js is trying to access
library.lang = {
// code
} // code events.js but it’s not loaded
} library.string = yet
{
// code
}
43. Dojo’s <1.7 Solution
“provide” registers this page of code as “a class” (but
actually just an object).
dojo.provide(“dijit.Dialog”);
44. Dojo’s <1.7 Solution
“provide” registers this page of code as “a class” (but
actually just an object).
dojo.provide(“dijit.Dialog”);
dojo.require(“dijit.form.Button”);
“require” tells Dojo that the provided code depends
upon the required code. Dojo guarantees that the
required code is loaded before the provided code is
executed.
46. How Dojo <1.7 Worked
Script files were pulled in as text with XHR.
-= XHR =-
[dom.js]
code
code
code
require(‘event’)
library.dom = {
// code
}
47. How Dojo <1.7 Worked
Script files were pulled in as text with XHR.
One at a time, each text file is eval’d into
JavaScript.
synchronously!
-= XHR =- -= EVAL =-
[dom.js] [dom.js] [dom.js]
code code code
code code code
code code code
require(‘event’) require(‘event’) require(‘event’)
library.dom = { library.dom = { library.dom = {
// code // code // code
} } }
50. Dojo <1.7 Problems
XHR load has same-origin restrictions
Special, complex, XD loader was needed
51. Dojo <1.7 Problems
XHR load has same-origin restrictions
Special, complex, XD loader was needed
Eval’d code totally fubar’d syntax-error line
numbers
52. Dojo <1.7 Problems
XHR load has same-origin restrictions
Special, complex, XD loader was needed
Eval’d code totally fubar’d syntax-error line
numbers
Synchronous XHR is very slow
53. Dojo <1.7 Problems
XHR load has same-origin restrictions
Special, complex, XD loader was needed
Eval’d code totally fubar’d syntax-error line
numbers
Synchronous XHR is very slow
Some environments do not allow eval (like Adobe
AIR)
54. Dojo <1.7 Problems
XHR load has same-origin restrictions
Special, complex, XD loader was needed
Eval’d code totally fubar’d syntax-error line
numbers
Synchronous XHR is very slow
Some environments do not allow eval (like Adobe
AIR)
eval executes differently across browsers
55. Dojo <1.7 Problems
XHR load has same-origin restrictions
Special, complex, XD loader was needed
Eval’d code totally fubar’d syntax-error line
numbers
Synchronous XHR is very slow
Some environments do not allow eval (like Adobe
AIR)
eval executes differently across browsers
Developers are taught that eval is evil
59. Async
var Employee = require("Employee");
function Manager () { }
Manager.prototype = new Employee(); [ ERROR ]
60. Async
var Employee = require("Employee");
function Manager () { }
Manager.prototype = new Employee(); [ ERROR ]
The Employee code is loaded async, so it happens in
the background while Manager is invoked, which
means Employee is not ready and an error occurs.
65. document.write
write(‘<script src=”Store.js” />’);
write(‘<script src=”Employee.js” />’);
No access to the script’s dependencies
Does not work after page load
Blocks page rendering
67. appendChild(‘script’);
head = document.getElementsByTagName('head')[0];
script = document.createElement('script');
script.src = url;
head.appendChild(script);
No access to the script’s dependencies
68. appendChild(‘script’);
head = document.getElementsByTagName('head')[0];
script = document.createElement('script');
script.src = url;
head.appendChild(script);
No access to the script’s dependencies
Has same async issues
73. Function Wrapping
dependency
dependency
dependency
code_for_loader_to_execute = function(){
return code_to_be_converted_to_module_later
}
Wrapping code in function allows the loader to
control when invocation needs to occur
74. Function Wrapping
dependency
dependency
dependency
code_for_loader_to_execute = function(){
return code_to_be_converted_to_module_later
}
Wrapping code in function allows the loader to
control when invocation needs to occur
All code can defer until after all dependencies are
determined and loaded
77. AMD’s Methods
“define” registers this page of code as “a class”.
define();
require();
“require” loads in the requested modules and provides
them in a callback function.
79. Anatomy of AMD - define()
define(
[
“./depA”,
“./depB”
], function(depA, depB){
var myModule = {};
return myModule;
}
);
* There are other argument options, but these are the most
common.
80. Anatomy of AMD - define()
One of two
globals used in
the spec
define(
[
“./depA”,
“./depB”
], function(depA, depB){
var myModule = {};
return myModule;
}
);
* There are other argument options, but these are the most
common.
81. Anatomy of AMD - define()
One of two Dependencies list defined
globals used in as an array in the first
the spec argument
define(
[
“./depA”,
“./depB”
], function(depA, depB){
var myModule = {};
return myModule;
}
);
* There are other argument options, but these are the most
common.
82. Anatomy of AMD - define()
One of two Dependencies list defined
globals used in as an array in the first
the spec argument
The second
define(
[ argument is the
“./depA”, Factory which is
“./depB” consumed when
], function(depA, depB){ module is requested
var myModule = {};
return myModule;
}
);
* There are other argument options, but these are the most
common.
83. Anatomy of AMD - define()
One of two Dependencies list defined
globals used in as an array in the first
the spec argument
The second
define(
[ argument is the
“./depA”, Factory which is
“./depB” consumed when
], function(depA, depB){ module is requested
var myModule = {}; Dependencies
return myModule; passed as factory’s
} arguments
);
* There are other argument options, but these are the most
common.
84. Anatomy of AMD - define()
One of two Dependencies list defined
globals used in as an array in the first
the spec argument
The second
define(
[ argument is the
“./depA”, Factory which is
“./depB” consumed when
], function(depA, depB){ module is requested
var myModule = {}; Dependencies
return myModule; passed as factory’s
} arguments
All of your module
);
magic happens here,
complete with scope
isolation
* There are other argument options, but these are the most
common.
85. Anatomy of AMD - define()
One of two Dependencies list defined
globals used in as an array in the first
the spec argument
The second
define(
[ argument is the
“./depA”, Factory which is
“./depB” consumed when
], function(depA, depB){ module is requested
var myModule = {}; Dependencies
return myModule; passed as factory’s
} arguments
All of your module
);
magic happens here,
complete with scope
isolation
Looks like a class, smells
like a class... * There are other argument options, but these are the most
common.
87. Anatomy of AMD - require()
require(
[
“library/depA”,
“library/depB”
], function(depA, depB){
depA.doSomething();
depB.someMore();
}
);
* There are other argument options, but these are the most
common.
88. Anatomy of AMD - require()
The other global
require(
[
“library/depA”,
“library/depB”
], function(depA, depB){
depA.doSomething();
depB.someMore();
}
);
* There are other argument options, but these are the most
common.
89. Anatomy of AMD - require()
Modules, or “Imports” list
The other global defined as an array in the first
argument
require(
[
“library/depA”,
“library/depB”
], function(depA, depB){
depA.doSomething();
depB.someMore();
}
);
* There are other argument options, but these are the most
common.
90. Anatomy of AMD - require()
Modules, or “Imports” list
The other global defined as an array in the first
argument
require( Callback fires when
[
modules are loaded
“library/depA”,
“library/depB” and ready
], function(depA, depB){
depA.doSomething();
depB.someMore();
}
);
* There are other argument options, but these are the most
common.
91. Anatomy of AMD - require()
Modules, or “Imports” list
The other global defined as an array in the first
argument
require( Callback fires when
[
modules are loaded
“library/depA”,
“library/depB” and ready
], function(depA, depB){
depA.doSomething(); Modules passed as
depB.someMore(); callback’s
} arguments
);
* There are other argument options, but these are the most
common.
92. Anatomy of AMD - require()
Modules, or “Imports” list
The other global defined as an array in the first
argument
require( Callback fires when
[
modules are loaded
“library/depA”,
“library/depB” and ready
], function(depA, depB){
depA.doSomething(); Modules passed as
depB.someMore(); callback’s
} arguments
);
Modules are ready to
access here
* There are other argument options, but these are the most
common.
93. Anatomy of AMD - require()
Modules, or “Imports” list
The other global defined as an array in the first
argument
require( Callback fires when
[
modules are loaded
“library/depA”,
“library/depB” and ready
], function(depA, depB){
depA.doSomething(); Modules passed as
depB.someMore(); callback’s
} arguments
);
Modules are ready to
access here
Looks like “define”! Simple!
* There are other argument options, but these are the most
common.
95. Why is ASYNC fast anyway?
In this context, “async” refers to allowing the browser
to load the scripts natively. It can load many scripts at
once, concurrently.
96. Why is ASYNC fast anyway?
The “sync” loader needed to block all other processes
while a script was loaded.
100. Plugins
The bang! symbol represents a plugin that
performs a special task.
require(["dojo", "dojo/domReady!"], function(dojo){
! doDomStuff();
});
define([
“dijit/Widget”,
“dojo/text!myTemplate.html”
], function(Widget, template){
// build a widget
});
101. Plugins
The bang! symbol represents a plugin that
performs a special task.
domReady! is a common plugin that prevents
the callback from firing until the DOM is in
fact... ready.
require(["dojo", "dojo/domReady!"], function(dojo){
! doDomStuff();
});
define([
“dijit/Widget”,
“dojo/text!myTemplate.html”
], function(Widget, template){
// build a widget
});
102. Plugins
The bang! symbol represents a plugin that
performs a special task.
domReady! is a common plugin that prevents
the callback from firing until the DOM is in
fact... ready.
require(["dojo", "dojo/domReady!"], function(dojo){
! doDomStuff();
});
define([
“dijit/Widget”,
“dojo/text!myTemplate.html”
], function(Widget, template){
// build a widget
});
text! knows that it is reading text or HTML
and possibly applies transforms to it.
106. Packages
A package.json file will help describe your code, its
external dependencies, and how it should be used.
{
"name": "clubajax.js",
"description": "Club AJAX Base Library",
"licenses": [{
"type": "AFLv2.1",
"url": "http://dojo/LICENSE"
}],
"bugs": "",
"keywords": [],
"homepage": "http://clubajax.org/",
"dependencies": {},
"dojoBuild": "clubajax.profile.js",
"main": "./main"
107. Packages
A package.json file will help describe your code, its
external dependencies, and how it should be used.
{
"name": "clubajax.js",
"description": "Club AJAX Base Library",
"licenses": [{
"type": "AFLv2.1",
"url": "http://dojo/LICENSE"
}],
"bugs": "",
"keywords": [],
"homepage": "http://clubajax.org/",
"dependencies": {},
"dojoBuild": "clubajax.profile.js",
"main": "./main"
“dojoBuild” points to the profile, and “main” points to
the master file that knows of all the files in the
package.
113. AMD Authors
Kevin Dangoor
Authored blog post: “What
Server Side JavaScript Needs”
Founded CommonJS
Expressed the need for JS
modules and packages
RequireJS based on CommonJS
module spec
115. AMD Authors
Rawld Gill
Wrote the Dojo 1.7 loader and
Node.js build tool
key contributor to AMD spec
Authored all AMD plugins (text,
i18n, domReady, ready)
dojo bootstrap (kernel and base
load)
dojo's has.js implementation
(enhanced from standard
version)
117. AMD Authors
Kris Zyp
Of course he helped. What is
there that Kris Zyp DOESN’T
do??
118. AMD Libraries
The following libraries are either AMD-
compliant or AMD loaders
jQuery 1.7
Dojo 1.7
MooTools 2.0
EmbedJS
curl.js
119. More AMD Info
https://github.com/amdjs/amdjs-api/wiki/AMD
http://www.commonjs.org/
http://www.commonjs.org/specs/
http://dojotoolkit.org/reference-guide/loader/
index.html#loader-index
http://dojotoolkit.org/reference-guide/loader/amd.html#loader-
amd
http://arstechnica.com/web/news/2009/12/commonjs-effort-
sets-javascript-on-path-for-world-domination.ars
http://requirejs.org/docs/history.html
http://www.commonjs.org/history/
https://groups.google.com/group/amd-implement?pli=1
✴ Special credit to Rawld Gill of Alto Visio for his in depth
explanations of Dojo Loader and Build Tool
✴ And a very special credit to James Burke - since most of the
information in this presentation came from the RequireJS pages.