VTEX namespaced and forked version of curl.js
npm install vtex-curl-amdcurl (cujoJS resource loader)
=====================
What is curl.js?
================
curl.js is a small and very fast AMD-compliant asynchronous loader.
Size: ~4KB (gzipped) using Google's Closure Compiler.
If you'd like to use curl.js for non-AMD modules (ordinary javascript files),
you'll want to use the legacy loader.
curl.js, like all async loaders, cannot circumvent browsers' security
restrictions when using the file: protocol. Therefore, you must use
curl from a page served from a web server (i.e. using http: or https:).
Trying to run curl.js from a page loaded from your local file system
will not work correctly in all browsers.
What the heck is "cujoJS"? cujoJS is the JavaScript Architectural Toolkit.
More info: cujojs.com
What is "cram"? cram (cujoJS resource assembler) is the build tool companion to
curl.js. You use cram to compile all of your modules into a small number of
javascript files which are loaded much faster into the browsers.
----------------------------------------
Features at a glance:
=====================
* Loads AMD-formatted javascript modules in parallel
* Loads CommonJS/node modules (v1.1 when wrapped in a define())
* Loads CommonJS/node modules (unwrapped when using the cjsm11 loader)
* Loads non-AMD javascript files in parallel, too.
* Loads CSS files and text files in parallel
* Waits for dependencies (js, css, text, etc) before executing javascript
* Waits for domReady, if desired
* Allows for virtually limitless combinations of files and dependencies
* Tested with Safari 5+, IE6+, and recent Chrome, FF, Opera
More detailed information below and on the
wiki.
----------------------------------------
How to get support
===============
1. Go to the issues section of the curl repo
(https://github.com/cujojs/curl/issues) and search for an answer to your
question or problem.
2. If no answer exists, file a new ticket! Somebody will typically respond
within a few hours.
It's that easy.
Got more in-depth questions? Browse the
cujoJS discussion group or
come chat with us on freenode @ #cujojs.
See the wiki for information about using
curl.js with jQuery, dojo, or underscore.
----------------------------------------
What's New?
=======
* 0.8.10
* Add moduleType and main properties to bower.json and package.json.
* 0.8.9
* Protect more API functions in plugins and loaders from closure compiler's
aggressive obfuscation.
* Switch to newer //# sourceURL syntax.
* Stop doubling the ".js" on the sourceURL.
* Ensure that define is undefined when wrapping cjs/node modules.
* 0.8.8
* Stop double-appending .css extension in css! plugin.
(thanks @stanislawosinski!)
* 0.8.7
* Fix botched release wherein some dummy forgot to bin/make-all.sh.
* 0.8.6
* Cram plugins: hide legacy plugin's define from cram parser.
* 0.8.5
* Cram plugins: plugins are now responsible for resolving url/filepath.
* Cram plugins: legacy loader no longer fails to add a .js extension
when there are dots in the file name.
----------------------------------------
API at a glance
===============
At it's core, curl.js provides an AMD environment:
``javascript`
define(['dep1', 'dep2', 'dep3' / etc /], factory);
define(['dep1', 'dep2', 'dep3' / etc /], module);
define(module);
define(name, ['dep1', 'dep2', 'dep3' / etc /], factory);
define(name, ['dep1', 'dep2', 'dep3' / etc /], module);
define(name, module);
These all define a module per the AMD specification.
* ['dep1', 'dep2', 'dep3']: Module names or plugin-prefixed resource files.
Dependencies may be named 'require', 'exports', or 'module' and will behave
as defined in the CommonJS Modules 1.1 proposal.
* factory: Function called to define the module. Each dependency is
passed as a parameter to the factory.
* module: Any javascript object, function, constructor, or primitive
* name: String used to name a module. This is not necessary nor is it
recommended. "Named modules" are typically only created by build tools
and AMD bundlers.
----------------------------------------
`javascript`
define(function (require, exports, module) {
var dep1 = require('app/foo');
exports.foo2 = function () { return foo() + 2; };
});
Defines a module using the AMD-wrapped-CommonJS format. If a factory function
has parameters, but the dependency list is missing, this format is assumed.
The exports and module parameters are optional, but when specified, must
be in this exact order.
----------------------------------------
`javascript`
define(function (require) {
var dep1 = require('app/foo');
return function () { return foo() + 2; };
});
Another variation on AMD-wrapped-CommonJS that uses require() in the
tidy CommonJS manner, but returns the exports as per typical AMD.
----------------------------------------
`javascript`
define(['require', 'exports', 'module'], function (require, exports, module) {
var dep1 = require('app/foo');
exports.foo2 = function () { return foo() + 2; };
});
Another way to gain access to the CommonJS-like variables, require,exports, module. When specified in the dependency list, these
"pseudo-modules" are provided as arguments to the factory function.
----------------------------------------
`javascript`
var dep1 = require('app/foo');
exports.foo2 = function () { return foo() + 2; };
curl.js also supports unwrapped CommonJS modules (and node.js modules)
via the cjsm11 module loader. To use this module loader for a package, say
Backbone, you would provide it to a package config, like this:
`javascript`
curl.config({
packages: [
{
name: 'backbone',
location: 'bower_components/backbone'
main: 'backbone.min.js',
config: { moduleLoader: 'curl/loader/cjsm11' } / <-- hey! /
}
]
});
Read the notes in the src/curl/loader folder and the cjsm11.js file for
more information about loading CommonJS and node.js modules.
-----
curl.js's global API is for bootstrapping an app. You would typically only use
this API once in your application to load the main module of your application.
For a complete description, check out the wiki.
`javascript`
curl(['main', 'other', 'another' / etc /], callback, errorback);
Loads a module named "main" along with two other modules and the executes
callback, handing it the exported values of the modules as parameters.
* ['main', 'other', 'another']: Module names or plugin-prefixed resource files.
* callback: Function to receive modules or resources. This is where you'd
typically start up your app. Optional.
* errorback: Function to receive an exception parameter when loading fails.
Optional.
---------
`javascript`
curl(['main', 'other', 'another' / etc /])
.then(callback, errorback);
Promises-based API for executing callbacks.
* ['main', 'other', 'another']: Module names or plugin-prefixed resource files.
* callback: Function to receive modules or resources. Optional.
* errorback: Function to call if an exception occurred while loading. Optional.
* For full CommonJS Promises/A+ compliance, use when.js
* when(curl(['dep1'])).then(callback);
---------
`javascript`
curl(config, ['main' / etc /], callback, errorback);
Specify configuration options, load dependencies, and execute callback.
* config: Object containing curl configuration options (paths, etc.)
* ['main']: Module name(s).
* callback: Function to receive modules or resources. Optional.
* errorback: Function to call if an exception occurred while loading. Optional.
---------
`javascript`
curl(['main', 'domReady!' / etc /]).then(
callback,
errorback
);
`javascript`
curl(['main', 'domReady!' / etc /], function (main) {
// do some bootstrapping here
});
Executes the callback when the dom is ready for manipulation AND
all dependencies have loaded.
---------
`javascript`
curl(['domReady!', 'js!nonAMD.js!order', 'js!another.js!order']), function () {
/ do something cool here /
});
Executes the function when the non-AMD javascript files are loaded and
the dom is ready. The another.js file will wait for the nonAMD.js file
before executing.
Note: Please use curl.js's new legacy loader for much more flexible and
sensible loading of non-AMD scripts. Please read the docs in the
src/curl/loader folder for more information.
Note: if a file supports AMD or CommonJS module formats, you can not use the
js! plugin on that file.
---------
`javascript`
curl(['js!nonAMD.js'])
.next(['dep1', 'dep2', 'dep3'], function (dep1, dep2, dep3) {
// do something before the dom is ready
})
.next(['domReady!'])
.then(
function () {
// do something after the dom is ready
},
function (ex) {
// show an error to the user
}
);
Executes callbacks in stages using .next(deps, callback).
Note: .next() does not load resources in parallel. Therefore, it is apreloads
last resort when other options do not satisfy your use case. You should
use the config option and/or the legacy loader
whenever possible.
---------
`javascript`
curl = {
baseUrl: '/path/to/my/js',
pluginPath: 'for/some/reason/plugins/r/here',
paths: {
curl: 'curl/src/curl',
cssx: 'cssx/src/cssx',
my: '../../my-lib/'
},
apiName: 'someOtherName'
};
If called before the
curl(
// fetch all of these resources ("dependencies")
[
'stuff/three', // an AMD module
'cssx/css!stuff/base', // a css file
'i18n!stuff/nls/strings', // a translation file
'text!stuff/template.html', // an html template
'domReady!'
]
)
// when they are loaded
.then(
// execute this callback, passing all dependencies as params
function (three, link, strings, template) {
var body = document.body;
if (body) {
body.appendChild(document.createTextNode('three == ' + three.toString() + ' '));
body.appendChild(document.createElement('br'));
body.appendChild(document.createTextNode(strings.hello));
body.appendChild(document.createElement('div')).innerHTML = template;
}
},
// execute this callback if there was a problem
function (ex) {
var msg = 'OH SNAP: ' + ex.message;
alert(msg);
}
);
`
The file structure for this example would look as follows:
js/
curl/
plugin/
i18n.js
text.js
domReady.js
cssx/
src/
cssx/
css.js
my/
stuff/
nls/
strings.js
base.css
template.html
three.js
curl.js
----------------------------------------
What is an asynchronous loader?
===============================
Web apps, especially large ones, require many modules and resources. Most of
these modules and resources need to be loaded at page load, but some may be
loaded later, either in the background or "just in time". They also need to be
loaded as quickly as possible.
The traditional way to load javascript modules is via a