A Javascript module loader
by Henrique Filho @ Avenue Code
hfilho@avenuecode.com
hfilho@avenuecode.com
Jan 14th, 2014
AGENDA
- Prerequisites
- The Web Today
- CommonJS
- AMD
- RequireJS
- Question
- Differences between Define and Require
_____________________________________________
A javascript module loader with Require.js
AGENDA
- How to Struct a project with RequireJS
- BaseURL and Paths
- Maps
- Shims
- Config
- Structure example
-
Conclusion
- Learn More
- Assignment - Building a Require JS structure
_____________________________________________
A javascript module loader with Require.js
PRerequisites
Javascript intermediate/advanced
The Web Today
- Immediately executed factory function
(function () { var $ = this.jQuery; this.myExample = function () {}; }());
-
The dependencies are very weakly stated:
- The developer needs to know the right dependency order
- Not scalable
- Can generate cyclic definitions
_____________________________________________
A javascript module loader with Require.js
Common JS
- Common JS: Javascript not just for browsers anymore
- Javascript Standard Library
- Develop using Common JS API's and then run the application across different JavaScript interpreters and host environments
- Standards Examples: Binary, Console, I/O, Encoding, Modules, Packages, Unit Testing etc
_____________________________________________
A javascript module loader with Require.js
COMMON JS
What can we do?
-
Server-side JavaScript applications (node.js)
-
Command line tools (for Browsers)
-
Desktop GUI-based applications (Wakanda)
-
Hybrid applications (Titanium, Adobe AIR)
_____________________________________________
A javascript module loader with Require.js
Common JS
Advantages on Require JS?
-
Specify a way to load dependencies
-
Asynchronous definitions
-
Modules transportation
- Scalable project: Solve complexity of huge web sites
_____________________________________________
A javascript module loader with Require.js
AMD
-
AMD:
Asynchronous Module Definition
- Modules and its dependencies can be asynchronous loaded
- Problems to Solve:
-
Performance
- Usability
- Debugging
- Cross-Domain access
-
Performance
_____________________________________________
A javascript module loader with Require.js
AMD
define(id?, dependencies?, factory);
// Calling define with module ID, dependency array and factory function
define('myModule', ['dep1', 'dep2'], function (dep1, dep2) {
// Define the module value by returning a value.
return function () {};
});
-
You should avoid naming modules yourself, and only place one module in a file while developing.
-
For tooling and performance, a module solution needs a way to identify modules in built resources.
_____________________________________________
A javascript module loader with Require.js
AMD
-
AMD solves the issues by
- Register the factory function by calling define()
- Pass dependencies as an array of string values, do not grab globals
- Only execute the factory function once all the dependencies have been loaded and executed
- Pass the dependent modules as arguments to the factory function
_____________________________________________
A javascript module loader with Require.js
Require JS
-
Require JS:
JavaScript file and module loader
-
Uses AMD to structure your dependencies
- Allow the developer to configure all libraries and their dependencies once and avoids cyclic dependencies
- Improvements:
- Speed (Less HTTP Requests)
- Quality of your code
- Structured project
_____________________________________________
A javascript module loader with Require.js
Require JS
-
Project Structure using Require JS library
- project-directory/
- project.html
- scripts/
- main.js
- require.js
- helper/
- util.js
_____________________________________________
A javascript module loader with Require.js
Require JS
-
Different approach to script loading than traditional <script> tags
<!DOCTYPE html>
<html>
<head>
<title>My Sample Project</title>
<!-- data-main attribute tells require.js to load
scripts/main.js after require.js loads. -->
<script data-main="scripts/main" src="scripts/require.js"></script>
</head>
<body>
<h1>My Sample Project</h1>
</body>
</html>
_____________________________________________
A javascript module loader with Require.js
REQUIRE JS
- Inside of main.js
- You can use require() to load any other scripts you need to run.
- This ensures a single entry point, since the data-main script you specify is loaded asynchronously.
require(["helper/util"], function(util) {
// This function is called when scripts/helper/util.js is loaded.
// If util.js calls define(), then this function is not fired until
// util's dependencies have loaded, and the util argument will hold
// the module value for "helper/util"
});
_____________________________________________
A javascript module loader with Require.js
REquire JS
-
AMD and RequireJS :
Simplified CommonJS wrapper
define(function(require, exports, module) { var a = require('a'), b = require('b'); // Return the module value return function () {}; } );
- Direct alignment of dependency name to the local variable used for that dependency
- Uses Function.prototype.toString() function to get the string value of the contents
_____________________________________________
A javascript module loader with Require.js
Question
-
Eager loading:
you do everything when asked. Multiply two matrices. You do all the calculations.
-
Over-eager loading: you try to anticipate what the user will ask for and preload it
-
Lazy loading:
you only do a calculation when required. Don't do any calculations until you access an element of the result matrix
It uses LAZY LOADING to manage dependencies!
_____________________________________________
A javascript module loader with Require.js
Differences Between Require and Define
- define() is to create modules such as AMD
- Well-scoped object that avoids polluting the global namespace
- Only one module per file (name-to-file-path lookup algorithm)
- Any return value
- require() is to use in call hierarchy of JS files
- Reuse of defined modules
_____________________________________________
A javascript module loader with Require.js
How to Struct a Project with Require JS
- Usually, you specify a module and call with require
- What if you can't change the library lines (JQuery, Foundation)?
- What if you want to concentrate all dependencies without calling them on <script> tag?
-
What if you want change the location of your JS files and organize your dependencies?
USE A CONFIGURATION FILE
_____________________________________________
A javascript module loader with Require.js
BASEURL and Paths
-
baseURL: The root path to use for all module lookups
- If you don't specify, will attend the HTML current location
-
Paths: Path mappings for module names not found directly under baseUrl
_____________________________________________
A javascript module loader with Require.js
BaseURL and PATHS
Example
requirejs.config({
baseUrl: 'js/lib',
// If the module ID starts with "app",
// load it from the js/app directory.
// Paths are relative to the baseUrl,
// and never includes a ".js" extension since
// the paths config could be for a directory.
paths: {
app: '../app'
}
});
requirejs(['jquery', 'canvas', 'app/sub'],
function ($, canvas, sub) {
// Use either Jquery or Canvas libraries
});
_____________________________________________
A javascript module loader with Require.js
MAPS
- Maps: Instead of loading the module with the given ID, substitute a different module ID
- Larger projects that needs to use two different versions of the script
requirejs.config({ map: { '*': { 'foo': 'foo1.2' }, 'some/oldmodule': { 'foo': 'foo1.0' } } })
_____________________________________________
A javascript module loader with Require.js
ShIMS
- SHIM: Configure the dependencies, exports, and custom initialization for older and traditional "browser globals" scripts
- Scripts that do not use define() to declare the dependencies and set a module value
requirejs.config({
shim: {
'jquery.colorize': {
deps: ['jquery'],
exports: 'jQuery.fn.colorize'
}
}
});
_____________________________________________
A javascript module loader with Require.js
CONFIG
- Config: Pass down the configuration to a module
requirejs.config({
config: {
'bar': {
size: 'large'
},
'baz': {
color: 'blue'
}
}
});
define(function (require, exports, module) {
// Will be the value 'large'
var size = module.config().size;
});
_____________________________________________
A javascript module loader with Require.js
Structure EXAMPLE
require.config( {
baseUrl: "/script",
map: {
'*': {
'jquery': 'jquery-private'
},
'jquery-private': {
'jquery': 'jquery'
}
},
paths: paths,
shim: shim
} );
You can create variables to be used on require.config function
_____________________________________________
A javascript module loader with Require.js
Conclusion
- Common JS is a strong comunity that provides JS standards and are growing every day
- AMD is one of the standards used on Require JS to load dependencies asynchronous
- Require JS helps struct, config and improve performance of your app
- We must develop JS code based on good standards, improving performance and structure on the code
- Structured JS is the present and future
_____________________________________________
A javascript module loader with Require.js
Learn more
- CommonJS wiki - http://wiki.commonjs.org/wiki/CommonJS
- AMD wiki - https://github.com/amdjs/amdjs-api/wiki/AMD
- Require JS Official website - requirejs.org
- Advanced Usage: http://requirejs.org/docs/faq-advanced.html
- Egghead example - https://egghead.io/lessons/requirejs-introduction-to-requirejs
_____________________________________________
A javascript module loader with Require.js
Assignment
Get your multiple-choice quiz developed on Backbone and create the Require JS fundamentals, considering:
- You should have at least 5 libraries
-
At least two SHIM cases
- You must map the libraries
- Create paths as well
- Use at least one optimization criteria based on the optimizer page at requirejs.org (Optional Task)
- Explain the optimization with comments
- Send me the solution in a GitHub repo
_____________________________________________
A javascript module loader with Require.js
A Javascript Module Loader - RequireJS
By Avenue Code
A Javascript Module Loader - RequireJS
Learn how to use AMD to struct your code and fight against infinite requests. By Henrique Filho
- 4,467