curl.js is small, fast, extensible module loader that handles AMD, CommonJS Modules/1.1, CSS, HTML/text, and legacy scripts.

Related tags

Loaders curl
Overview

curl (cujoJS resource loader)

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.

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:

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.

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.


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.


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.


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:

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.

curl(['main', 'other', 'another' /* etc */], callback, errorback);

Loads a module named "main" along with two other modules and then 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.

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.
  • Note: curl.js's Promises are not compliant with ES6 or Promises/A+ so they may not behave as you'd expect. For full compliance, use when.js or any another ES6 Promise shim.
    • when(curl(['dep1'])).then(callback); or Promise.resolve(curl(['dep1'])).then(callback);

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.

curl(['main', 'domReady!' /* etc */]).then(
	callback,
	errorback
);
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.


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.


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 a last resort when other options do not satisfy your use case. You should use the preloads config option and/or the legacy loader whenever possible.


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 <script> that loads curl.js, a global curl var will configure curl.js when it loads. All of the configuration parameters are optional. curl.js tries to do something sensible in their absence. :)

Some common configuration options:

  • baseUrl: the root folder to find all modules, default is the document's folder
  • paths: a mapping of module paths to relative paths (from baseUrl)
  • pluginPath: the place to find plugins when they are specified without a path (e.g. "css!myCssFile" vs. "cssx/css!myCssFile") and there is no paths mapping that applies.
  • apiName: an alternate name to curl and require for curl.js's global variable
  • apiContext: an object, rather than window, to place curl on when using apiName

A more complete list can be found on the wiki.


Very Simple Example

<script>

	// configure curl
	curl = {
		paths: {
			cssx: 'cssx/src/cssx/',
			stuff: 'my/stuff/'
		}
	};

</script>
<script src="../js/curl.js" type="text/javascript"></script>
<script type="text/javascript">

	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);
		}
	);

</script>

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 <SCRIPT> element in an HTML page. Similarly, CSS files are loaded via a <LINK> element, and text resources are either loaded in the page or via XHR calls.

The problem with <SCRIPT> and <LINK> elements is that a browser must execute them sequentially since it has no idea if one may depend on another. It just assumes the developer has placed them in the correct order and that there are dependencies. (The term "synchronous loading" is used to describe this process since the elements are executed in a single timeline.)

If there are no dependencies between two files, loading them sequentially is a waste of time. These files could be loaded and executed in parallel (i.e at the same time).

An asynchronous loader does just that: it loads javascript files (and other types of files) in parallel whenever possible.

curl.js has lots of company. Other async loaders include LABjs, Steal.js, yepnope.js, $script.js, the Backdraft loader (bdLoad), and RequireJS.

(a more complete list)


What is AMD?

Asynchronous Module Definition is a de facto standard for javascript modules that can be loaded by asynchronous loaders. It defines a simple API that developers can use to write their javascript modules so that they may be loaded by any AMD-compliant loader.

AMD Spec

The AMD proposal follows some parts of the CommonJS Modules proposal. Because of the way browsers load and evaluate scripts, AMD can't follow it completely without causing significant processing overhead. Instead, AMD allows us to place a lightweight wrapper around javascript modules to help work around the shortcomings.

Ultimately, both proposals (AMD and Modules 1.1) are in preparation for an official javascript modules specification and eventual implementation in browsers.

If you don't want to wait for official javascript modules, then don't. The future is now. AMD works now -- and it's awesome.

AMD's API focuses on one globally-available function: define() and some CommonJS-inspired variables, require(), exports, and module. require() specifies a list of dependent modules or resources that must be loaded before running a set of code. This code resides in a callback function that is executed asynchronously, i.e. it runs later, not in the current "thread". Specifically, it executes when all of the dependencies are loaded and ready.

The proposal does not mandate that require() be specified globally. In fact, at a global level, the concerns of a loader are about application bootstrapping and not about finding dependencies. To keep the confusion about these two concepts to a minimum, curl.js uses curl() for the public API. You may rename this API back to require() by supplying the apiName config param (apiName: "require"), but this is not recommended.

It's more important that the define() method be consistent. This is the method that tells the loader what modules have been loaded by a script. define() also specifies a list of dependencies and a callback function that defines and/or creates the resource when the dependencies are ready. Optionally, define() also takes a name parameter, but this is mainly for build tools and optimizers.

Inside the define(), the require() method acts like other AMD loaders.

AMD's API also helps code reuse by providing compatibility with CommonJS (server) modules. AMD-compliant loaders support the same require() syntax and argument signatures as server-side javascript (ssjs) modules.

The beauty of AMD loaders is their ability to remove the drudgery of manually managing dependencies. Since all dependencies are listed within the modules, the loader will ensure that everything is loaded into the browser -- and in the right order.


Can curl.js work with non-AMD and non-CommonJS javascript files?

Yes, but why would you? Once you start using AMD, you'll never go back! :)

You may use non-AMD javascript files by using the legacy loader like this:

curl.config({
	paths: {
		plainOldJsFile1: {
			location: 'js/plainOldJsFile1.js',
			config: { loader: 'curl/loader/legacy', exports: 'aGlobal' }
		},
		anotherPlainOldJsFile: {
			location: 'js/anotherPlainOldJsFile.js',
			config: {
				loader: 'curl/loader/legacy',
				exports: 'anotherGlobal',
				requires: [ 'plainOldJsFile1' ]
			}
		}
	}
});
curl(['anotherPlainOldJsFile']).then(
	function (anotherGlobal) {
		/* do something with your plain, boring javascript files */
	},
	function () {
		/* do something if any fail to load */
	}
);

Please read the docs in the src/curl/loader folder for more information.


Can curl.js load non-javascript files via plugins?

Yes, curl.js follows the CommonJS Loader Plugin specification, so you can use any compatible plugin. The following plugins are included:

js! -- loads non-AMD javascript files. more info on the wiki

text! -- loads text files

link! -- loads css files via a link element (simple, fast)

css! -- loads css files (lots of options)

domReady! -- resolves when the dom is ready for manipulation

async! -- resolves when a module signals it's ready

i18n! -- loads text strings and other locale-specific constants

Some plugin docs are on the wiki.

More documentation is available inside the source of these plugins!


How are modules loaded?

curl.js uses <script> element injection rather than XHR/eval for AMD modules. This allows curl.js to load cross-domain scripts as well as local scripts. CommonJS modules use XHR/eval so must be wrapped for "transport" if not on the same domain. Typically, you will bundle your modules before using them in production, anyways. Most bundlers will wrap CommonJS modules in AMD.

To find scripts and other resources, curl.js uses module names. A module name looks just like a file path, but typically without the file extension. If a module requires a plugin in order to load correctly, it will have a prefix delimited by a "!" and will also often have a file extension when a plugin may load different types of files.

Some examples of module names:

By default, curl.js will look in the same folder as the current document's location. For instance, if your web page is located at http://my-domain/apps/myApp.html, curl.js will look for the JsonRest module at http://my-domain/apps/dojo/store/JsonRest.js.

You can tell curl.js to find modules in other locations by specifying a baseUrl or individual packages for each of your libraries. For example, if you specify a baseUrl of /resources/ and the following paths:

packages: [
	{ name: "dojo", location: "third-party/dojo" },
	{ name: "css", location: "third-party/cssmojo/css" },
	{ name: "my", location: "my-cool-app-v1.3" },
	{ name: "my/lib/js", location: "old-js-libs" }
]

Then the modules listed above will be sought in the following locations:

  • /resources/third-party/dojo/store/JsonRest.js
  • /resources/my-cool-app-v1.3/lib/string/format.js
  • /resources/old-js-libs/plain-old-js.js
  • /resources/my-cool-app-v1.3/styles/reset.css
  • http://some-cdn/uber/module.js

Note: you will need to create a path to curl.js's plugins and other modules if the curl folder isn't directly under the same folder as your web page. curl.js uses the same mechanism to find its own modules.


What are AMD plugins?

AMD supports the notion of plugins. Plugins are AMD modules that can be used to load javascript modules -- or other types of resources. curl comes with several plugins already, including a text plugin (for templates or other text resources), two different css plugins, a dom-ready plugin, and several others.

Plugins are designated by a prefix on the name of the module or resource to be loaded. They are delineated by a ! symbol. The following example shows the use of some plugins:

define(
	[
		'text!myTemplate.html',
		'css!myCssFile'
	],
	function (templateString, cssLinkNode) {
		// do something with the template and css here
	}
);

Since plugins are just AMD modules, they would typically be referenced using their fully-pathed names. curl provides a pluginPath configuration option that allows you to specify the folder where [most of] your plugins reside so you don't have to specify their full paths. This also helps with compatibility with other AMD loaders.

If one or more of your plugins does not reside in the folder specified by the pluginPath config option, you can use its full path or you can specify a path for it in curl's paths config object.

// example of a fully-pathed plugin under the lib/cssx folder
define(['lib/cssx!myCssFile'], function (cssxDef) {
	// do some awesome css stuff here
});

Plugins can also have configuration options. Global options can be specified on curl's configuration object. Options can also be supplied to plugins via suffixes. Suffixes are also delineated by the ! symbol. Here's an example of a plugin using options:

// don't try to repair IE6-8 opacity issues in my css file
define(['css!myCssFile!ignore:opacity'], function (cssxDef) {
	// do some awesome css stuff here
});

How do I use curl.js?

  1. Learn about AMD-formatted javascript modules if you don't already know how.
  2. Clone or download curl to your local machine or server.
  3. Figure out the baseUrl and paths configuration that makes sense for your project.
  4. Check out the "API at a glance" section above to figure out which loading methodology you want to use.
  5. Study the "Very Simple Example" and some of the test files.
  6. Try it on your own files.

Too Many Modules!

I have dozens (or hundreds) of modules. Even with parallel loading, the performance sucks! What can I do about that?

True! No parallel loader can lessen the latency required to create an HTTP connection. If you have dozens or hundreds of files to download, it's going to take time to initiate each of the connections.

However, there are tools to that are designed to fix this problem! There are builders and compilers. dojo users are probably already familiar with dojo's build tool and optimizer. RequireJS comes with a build tool and Google's Closure compiler.

The build tool is used to concatenate several modules (and/or resources) into just a few files. It does this by following the dependency chain specified in the define() and require() calls. You can specify which top-level modules or resources are in each file and the build tool finds the rest.

After the build tool creates the concatenated files, the files can be passed into a compiler (also called a shrinker or compressor).

curl.js is compatible with RequireJS's build tool, r.js, but there's also cram. Cram is the cujoJS resource assembler.


Package Support

cujoJS supports packages. Packages are defined by the packages configuration parameter:

curl = {
	baseUrl: 'path/to/js',
	packages: {
		'my-package': {
			location: 'path/to/my-package',
			main: 'main/main-module-file',
			config: { /* package-specific configuration options */ }
		}
	}
};
curl = {
	baseUrl: 'path/to/js',
	packages: [
		{
			name: 'my-package',
			location: 'path/to/my-package',
			main: 'main/main-module-file',
			config: { /* package-specific configuration options */ }
		}
	]
};

The path property describes where to find the package in relation to the baseUrl parameter. The main and lib properties describe where to find modules inside the package. The main property gives the relative path to the package's main module.

In the example above, the main module of the package can be obtained as follows:

curl(['my-package'], callback);

and will be fetched from the following path:

path/to/js/path/to/my-package/main/main-module-file.js

Some other file in the package would be obtained as follows:

curl(['my-package/other-module'], callback);

and will be fetched from the following path:

path/to/js/path/to/my-package/other-module.js

Note that a package may also contain it's own embedded set of config options. Most, but not all, config options may be specified here. Specifically, you cannot specify any options that change the path or id of modules, such as paths, packages, plugins, or 'pluginPrefix.


What is cujoJS?

cujoJS is the JavaScript Architectural Toolkit. It employs MVC, IOC, AMD and lots of other TLAs. :) Our goal is to provide architectural tools and guidance. Find out more at cujoJS.com.

Kudos

Many thanks to Bryan Forbes (@bryanforbes) for helping to clean up my code and for making curl's domReady much more robust and help with dojo compatibility. More about Bryan: http://www.reigndropsfall.net/

Kudos also to James Burke (@jrburke) who instigated the AMD standard and paved the way to create AMD-style loaders. More about James: http://jrburke.com/about/

Shout out to Kris Zyp (@kriszyp) for excellent ideas and feedback and to Kyle Simpson (@getify) who is inarguably the godfather of javascript loading.

Comments
  • dojo integration.  Error when localRequire replaces dojo require implementation

    dojo integration. Error when localRequire replaces dojo require implementation

    dojo require implementation uses the has.js script to check for mobile dependencies and other features that the current browser may support. Curl.js inserts itself for require but does not have the methods "add" or "on" to name a few that dojo has amended to their require. The error experienced is that object function {}() has not method named "add". This is because in dojo has.js replaces the add method with function(){} if the require provided to the method does not have an add method. This is in dojo 1.7 and above

    opened by greghawk 42
  • module-v1.0 is not auto-adding .js -- bug or by design?

    module-v1.0 is not auto-adding .js -- bug or by design?

    Using:

    curl(['module-v1_0']);
    

    Will fetch 'module-v1_0.js' automatically. But using:

    curl(['module-v1.0']);
    // or
    curl(['module-v1.0.html']); // cross-domain html file include
    

    Will fetch 'module-v1.0', using '.0' as the extension (or 'module-v1.0.html' with '.html' as the extension).

    While this may appear to be a harmless distinction, it provides inconsistency, which may be unnecessarily confusing in implementation on a large scale. Isn't it true that if you do not use a plugin ('plugin!filename') that it is in fact a module? I'd say requiring ".js" on the end of every module is a reasonable expectation, as it already assumes this for no extension.

    If for whatever reason, someone wanted to include modules with a different extension, this could possibly be wrapped in a small plugin such as "mod!mymodule.mod".

    Thoughts?

    opened by asilvas 32
  • Isolated plugin for tests

    Isolated plugin for tests

    Could you start a plugin for isolation of modules for tests like https://github.com/JamesMaroney/requirejs-isolate/ I would like to do it myseft but it impact the dependency system that you understand much better than me :).

    feature fixed in dev 
    opened by n0rad 26
  • Defining paths for non-AMD modules

    Defining paths for non-AMD modules

    Hello John,

    I was expecting that defining a path for a non-AMD module (standard js file) would work as any other module, so I could do something like this:

    curl = {
            baseUrl:'js',
            paths:{
              jquery:'lib/jquery-1.7.1.min',
              jqueryui:'lib/jquery-ui-1.8.16.custom.min.js',
      }
    }
    

    Would allow me to later define modules depending on jqueryui:

    define(['js!jqueryui!order'], function(){ ... });
    

    Unfortunatelly it does not work:

    Uncaught Error: Script error or http error: js/jqueryui.js
    

    Since I depend on jqueryui on many places, having a path defined to it is very convenient when upgrading the module.

    feature request? :)

    regards,

    Manuel.

    opened by manast 22
  • Implement urlArgs feature for cache busting AMD modules

    Implement urlArgs feature for cache busting AMD modules

    • Server is telling client to cache files forever (good production practice)
    • Client AMD module changes
    • Client needs to alter the request path in order to cache bust
    • There seems no way to do this currently via Curl

    RequireJS provides this - http://requirejs.org/docs/api.html#config-urlArgs

    opened by ryan-blunden 20
  • css! Not good support in IE9 and Opera when cross domain

    css! Not good support in IE9 and Opera when cross domain

    In function isLinkReady, if we visit 'sheet.rules', it will throw a error -'Access is denied' in IE9. This will make isLinkReady return true, then it will break the loop of function ssWatcher below. Actually, link.readyState and onload is support in IE9, it could be complete the loading. And (sheet.cssRules || sheet.rules) would be true, not 'Access is denied' when readyState is 'complete'.

    The sample example: http://jsfiddle.net/6BeDS/2/ (By the way IE9 can reproduce the issue only you clean the cache, because IE will using the cache css, even you using ctrl+F5 )

    fixed in dev 
    opened by yaoazhen 20
  • dev055 branch returning

    dev055 branch returning "undefined" for all plugin-related paths

    Not sure if I'm doing something wrong, but I cannot get curl.js (I build the plugins into it using an already established make process) under the dev055 branch to work at all. When requesting:

      curl("js!http://domain.tld/test.js");
    

    All this does is request "undefined". Was this branch not ready for testing?

    cannot reproduce 
    opened by asilvas 19
  • WIP: WebWorker support

    WIP: WebWorker support

    I created a plugin to load a module as a worker, and modified curl.js to work from within a worker.

    There isn't any detection for worker support right now, which is the biggest missing feature for me.

    There are a few ways I thought of to do this:

    • The most obvious way (to me) would be to just require the file as normal in the worker plugin, perhaps using setTimeout to fake asynchronicity. I'm not sure if this is a good idea though.
    • Alternatively, a shim module could be added, to check for window.Worker and return Worker, whether it's fake or real.
    • Do something with has!, loading a non-worker module instead if the browser doesn't support Workers.

    Currently I've done the bare minimum to get it to work, suggestions for improvement are certainly welcome.

    opened by alanpearce 18
  • cjsm11 loader: detect upgraded modules?

    cjsm11 loader: detect upgraded modules?

    After a while of wondering why require('async') yielded an empty object, I found that it had AMD support and thus used define([], async);, leaving the empty object in module.exports which I probably received at first. Once found, the solution was easy of course: Just not using the cjsm11 loader.

    It would be nice however to handle upgrades gracefully, when an author of a previously cjs-only module adds AMD support later on. Would there be a way to make the cjsm11 loader detect the upgrade and prefer the define()d object? Maybe only if module.exports holds the same empty object that it was initialized with?

    Yours, MK

    opened by mk-pmb 17
  • Add global / package js! plugin configs to specify legacy options: exports and dependencies (like RequireJS's

    Add global / package js! plugin configs to specify legacy options: exports and dependencies (like RequireJS's "shim config")

    (Note: this feature would be the equivalent of RequireJS's shim options.)

    Allow the following global or package-specific configs:

    curl({
        plugins: {
            js: { 
                legacy: { // or "shim"
                    backbone: { exports: 'Backbone', deps: ["jquery", "lodash"] }
                }
            }
        }
    });
    
    curl({
        packages: [
            { name: 'backbone', location: 'here/foo', main: '../backbone.min'
                config: {
                    moduleLoader: 'curl/plugin/js',
                    legacy: { exports: 'Backbone', deps: ["jquery", "lodash"] }
                }
            }
        ]
    });
    
    opened by unscriptable 17
  • Syntax or http error when upgrading from 0.6.2 to 0.7.0

    Syntax or http error when upgrading from 0.6.2 to 0.7.0

    I'm currently on v0.6.2 of the kitchen-sink dist curl.js which is working fine with the following config:

    curl = {
        baseUrl:        '.',
        paths: {
            curl:           'lib.3p/cujojs/curl',
            jquery:         'lib.3p/jquery-1.8.2.min',
            knockout:       'lib.3p.extension/knockout',
            modernizr:      'lib.3p.extension/modernizr',
            sizzle:         'lib.3p/sizzle.min',
            underscore:     'lib.3p/underscore.min'         // TODO https://github.com/unscriptable/underscore/downloads!
        },
        packages: [
                { name:'aop', path:'lib.3p/cujojs/wire/aop', main:'./' },
                { name:'when', path:'lib.3p/cujojs/when', main:'./when' },
                { name:'wire', path:'lib.3p/cujojs/wire', main:'./wire' }
        ]
    };
    

    When I upgrade to curl v0.7.0 I get the following error:

    Syntax or http error: ./lib.3p/cujojs/curl/plugin/wire.js
    

    Seems it's now looking in the wrong place for wire.js (which is actually located at lib.3p/cujojs/wire.js) but there's no mention of curl/plugin path anywhere in my project!

    Any ideas ? Ta, Andy.

    opened by dizzib 17
  • cjsm11 loader hides a TypeError and falsely reports success

    cjsm11 loader hides a TypeError and falsely reports success

    ––> Details, demo code, screenshots <––

    This bug took me quite a while to understand, because when using the file:// protocol (which I did), a decoy non-error is reported at the same time as the real error is silenced:

    XML Parsing Error: not well-formed Location: file:///mnt/…/curl-cjsm11-bug/01-totally-common.js Line Number 1, Column 13

    opened by mk-pmb 0
  • Feature Request: Add syntax to bypass plugins

    Feature Request: Add syntax to bypass plugins

    It's easy to specify in a resourceId that a certain plugin shall be used. I'd like to be able to also specify that no plugin shall be used, even if a default plugin is configured. I suggest we use a ! right at the start of the resourceId for this hint.

    opened by mk-pmb 0
  • multiple anonymous defines

    multiple anonymous defines

    For the record, I encountered this problem one day out of the blue and thankfully only lost a couple of hours before I tried disabling the browser extensions which fixed the problem (but left me without an excellent extension :( )

    opened by molipha 2
  • Promise.then doesn't wait

    Promise.then doesn't wait

    i.e.:

    require(['bootstraps/standard'])
        .then(() => (
            new Promise(resolve => setTimeout(() => resolve(), 500))
                .then(() => console.log('foo')))
        )
        .then(() => console.log('bar'))
    

    bar will fire before foo.

    I'm happy to cast the promise using Promise.resolve, but can this be documented?

    opened by OliverJAsh 5
  • Multiple bundles

    Multiple bundles

    Hello, I've been facing a problem for some time and I have no clue what to do.

    I work on a very large system with most of it's functionally implemented on the front end. We have more than 2mb on minified javascript files that needs to load in different parts of the system.

    When I just curl every module, everything runs fine. But as you may know, it makes A LOT of http requests, around 100 just for the system to load.

    So we decided to use CRAM to create bundles with all modules included. A single bundle just kept growing and growing, while most of it's modules weren't being used but had to be transfered.

    Then we split this bundle into multiple by it's functions. The dashboards got one, the login page one, the graphics one and etc.

    Everything was running fine until these bundles had to share modules between then.

    Everytime a bundle was loaded with a module in it that was already loaded, curl would throw a "Duplicate define" error.

    The only workaround that I could think was to remove the shared files from all bundles and let it load just in time, but then, there are a lot of http requests.

    Do you have any suggestion by which way we should go? Is having a giant bundle the answer?

    A problem with big bundles, is that all modules are loaded eagerly instead of JIT, so having a big bundle would result in poor initial performance. (https://github.com/cujojs/curl/issues/258)

    Thank you all, and sorry for any english mistakes.

    opened by fedevegili 17
Releases(0.8.13)
  • 0.8.13(Jan 19, 2016)

  • 0.8.12(Nov 5, 2014)

    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.

    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.

    We've added some info in the README, as well as some links to various RaveJS resources and a migration guide.

    Watch rave to stay up to date!

    Source code(tar.gz)
    Source code(zip)
  • 0.8.10(Apr 2, 2014)

  • 0.8.9(Feb 12, 2014)

    * 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.
    
    Source code(tar.gz)
    Source code(zip)
  • 0.8.8(Jan 17, 2014)

  • 0.8.7(Dec 20, 2013)

  • 0.8.6(Dec 19, 2013)

  • 0.8.5(Dec 19, 2013)

    * 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.
    
    Source code(tar.gz)
    Source code(zip)
  • 0.8.4(Oct 17, 2013)

    The experimental data-curl-run HTML attribute is now official and is documented in the wiki. You can use it to bootstrap an app with curl.js. See the wiki for more information.

    Source code(tar.gz)
    Source code(zip)
  • 0.8.3(Oct 15, 2013)

    • Export legacy-loaded modules with normal AMD/CommonJS module ids (thanks @mmacaula!)
    • Build curl/debug into curl/dist/debug/curl.js correctly.
    Source code(tar.gz)
    Source code(zip)
  • 0.8.2(Oct 3, 2013)

    • Run compile.sh from anywhere (thanks @webpro!)
    • Restore quotes to cram text plugin output (thanks @gehan!)
    • Correctly bake-in the locale module in the kitchen-sink dist build.
    Source code(tar.gz)
    Source code(zip)
  • 0.8.0(Aug 23, 2013)

    • Adds new curl/loader/legacy module loader that provides similar functionality to RequireJS's "shim config".
    • Adds dontAddFileExt config option functionality to js! plugin and curl/loader/legacy module loader.
    • Fixes configuration context mixups. Modules will get their package's config unless they are loaded explicitly via a plugin and that plugin has a custom configuration.
    • Paths can now be objects like packages and can have all of the same properties, except main, i.e. location (or path), config, name.
    • Fixes an issue in node on windows wherein C: was seen as a web protocol.
    • Updates READMEs in the plugin and loader folders.
    • Drops dojo 1.6 compatibility in the "kitchen sink" distribution.
    • Adds new dojo 1.8 distribution.
    Source code(tar.gz)
    Source code(zip)
  • 0.7.6(Aug 21, 2013)

    * Adds compatibility with dojo 1.8 and 1.9, including the ability to provide
      `has` configuration via `curl.config()`. (Requires use of the
      curl/shim/dojo18 shim.)
    * Fixes many bugs in the i18n and cjsm11 cram (build) plugins.
    * Stops encoding the output of the cram plugins that emit javascript code.
    * Adds code documentation improvements in the plugins.
    * Applies Seriously overdue README updates.
    * Restores text! plugin functionality to the "kitchen sink" build.
    
    Source code(tar.gz)
    Source code(zip)
  • 0.7.5(Jul 30, 2013)

    • Can now resolve relative plugin ids in local require (bug fix).
    • Fixes #199: Fallback to doc.getElementsByTagName when doc.scripts does not exist.
    Source code(tar.gz)
    Source code(zip)
Owner
The Javascript Architectural Toolkit
The Javascript Architectural Toolkit
A Module Loader for the Web

A Module Loader for the Web Sea.js is a module loader for the web. It is designed to change the way that you organize JavaScript. With Sea.js, it is p

seajs 8.3k Jan 3, 2023
Dynamic ES module loader

SystemJS SystemJS is a hookable, standards-based module loader. It provides a workflow where code written for production workflows of native ES module

null 12.4k Dec 29, 2022
:skull: An ancient tiny JS and CSS loader from the days before everyone had written one. Unmaintained.

LazyLoad Note: LazyLoad is no longer being maintained. I'm not responding to issues or pull requests, since I don't use this project anymore and don't

Ryan Grove 1.4k Jan 3, 2023
Asyncronous JavaScript loader and dependency manager

$script.js - Async JavaScript loader & dependency manager $script.js is an asynchronous JavaScript loader and dependency manager with an astonishingly

Dustin Diaz 2.9k Jan 3, 2023
enterprise standard loader

ESL (Enterprise Standard Loader) ESL是一个浏览器端、符合AMD的标准加载器,适合用于现代Web浏览器端应用的入口与模块管理。 ESL is a browser-only, amd-compliant module loader. In modern web app

Baidu EFE team 833 Dec 16, 2022
Lightweight JavaScript module system.

modulejs Lightweight JavaScript module system. License The MIT License (MIT) Copyright (c) 2020 Lars Jung (https://larsjung.de) Permission is hereby g

Lars Jung 124 Dec 21, 2022
CSS optimization using critters for Nuxt

@nuxtjs/critters CSS optimization using critters for Nuxt Features Zero-configuration required Enables CSS Extraction Critical CSS automatically injec

Nuxt Community 76 Dec 26, 2022
Node.js loader for compiling ESM & TypeScript modules to CommonJS

cjs-loader Node.js require() hook to instantaneously transform ESM & TypeScript to CommonJS on demand using esbuild. Features Transforms ESM & TypeScr

esbuild kit 40 Dec 13, 2022
An npm package for demonstration purposes using TypeScript to build for both the ECMAScript Module format (i.e. ESM or ES Module) and CommonJS Module format. It can be used in Node.js and browser applications.

An npm package for demonstration purposes using TypeScript to build for both the ECMAScript Module format (i.e. ESM or ES Module) and CommonJS Module format. It can be used in Node.js and browser applications.

Snyk Labs 57 Dec 28, 2022
Fast and powerful CSV (delimited text) parser that gracefully handles large files and malformed input

Parse CSV with JavaScript Papa Parse is the fastest in-browser CSV (or delimited text) parser for JavaScript. It is reliable and correct according to

Matt Holt 11k Jan 6, 2023
"shuffle-text" is JavaScript text effect library such as cool legacy of Flash.

ShuffleText This is the JavaScript library for text effect such as Flash contents. Setup Script Install <script src="shuffle-text.js"></script> NPM In

Yasunobu Ikeda 96 Dec 24, 2022
Babel-plugin-amd-checker - Module format checking plugin for Babel usable in both Node.js the web browser environments.

babel-plugin-amd-checker A Babel plugin to check the format of your modules when compiling your code using Babel. This plugin allows you to abort the

Ferdinand Prantl 1 Jan 6, 2022
A labeler component that Lays out text and overlays textual decorations like labels, predictions, and relations based on given data and handles user interactions on tokens.

react-text-annotator react-text-annotator is a labeler component that: Lays out text and overlays textual decorations like labels, predictions, and re

Microsoft 25 Dec 11, 2022
curl for GraphQL with autocomplete, subscriptions and GraphiQL. Also a dead-simple universal javascript GraphQL client.

graphqurl graphqurl is a curl like CLI for GraphQL. It's features include: CLI for making GraphQL queries. It also provisions queries with autocomplet

Hasura 3.2k Jan 3, 2023
👨‍💻 • CURL client for Hacker News 📰 📰

⚙️ Hkkr.in ?? The easiest way to get your daily hourly Hacker News dosage! Usage • Contributing • ToDo Hkkr.in is a Curl client for Hacker News I spen

Ajith 23 Dec 11, 2022
A faster alternative to legacy node:querystring module

fast-querystring Fast query-string parser and stringifier to replace the legacy node:querystring module. Installation npm i fast-querystring Features

Yagiz Nizipli 95 Dec 17, 2022
🦄 0-legacy, tiny & fast web framework as a replacement of Express

tinyhttp ⚡ Tiny web framework as a replacement of Express ?? tinyhttp now has a Deno port (work in progress) tinyhttp is a modern Express-like web fra

v 1 r t l 2.4k Jan 3, 2023