curl.js is small, fast, extensible module loader that handles AMD, CommonJS Modules/1.1, CSS, HTML/text, and legacy scripts.
npm install curl-amdcurl (cujoJS resource loader)
=====================
We are very excited about RaveJS, the successor to curl.js. At its core, rave uses an ES6 Loader, rather than an AMD loader. However, rave can load many types of modules, including AMD. Therefore, rave will work with your application's AMD modules.
Rave's most exciting feature, however, is it's ability to eliminate the drudgery of bootstrapping and maintaining modern, modular web applications. If you've built a non-trivial AMD-based web app, you should be excited about rave, too.
Rave is definitely the future, so we're putting all of our effort into ensuring that RaveJS is as awesome as it can possibly be. Watch these RaveJS github projects to stay up to date:
* RaveJS/rave - Zero-configuration application bootstrap and development
* RaveJS/rave-start - Begin here for the simplest possible startup experience
* RaveJS/rave-start-angular - Begin here to create an AngularJS-based application
* snichme/rave-start-react - Begin here to create a React-based application
* fabricematrat/rave-start-cujo - Begin here to create a cujoJS-based application
This means that all development for curl.js and cram.js has stopped. For the foreseeable future, we will continue to respond to issues on github, as well as in the #cujojs room on freenode. However, keep in mind that there will be no further development, so some issues might not be resolved fully.
If you're as excited as we are about the future, consider helping us improve the curl-to-rave migration guide. There are many ways to architect curl-based applications, so your experience migrating your app from curl to rave is extremely valuable to other curl users.
Also, if you are interested in becoming the lead maintainer of curl.js and/or cram.js, please let us know on #cujojs!
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.12
* Add deprecation notice.
* Add links to Rave Starters.
* Add a link to the migration guide.
* 0.8.11
* Improve instructions for custom build thanks to @azazel75.
* Stop catching (and indirectly squelching) errors in callback functions. Fixes #281.
* Add version number at the beginning. Thanks @szepeviktor!
* Add note about config options that are not supported in embedded config.
* Added img! plugin and test cases. Thanks @asilvas!
* Recognize Windows absolute urls. C:\, e:/, etc. Thanks @doom777!
* Update to README.md to correct link to James Burke's site. Thanks @kryger!
* 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