A javascript module loading/creation system for the web including support for baking.
Last updated 8 years ago by jpike .
MIT · Original npm · Tarball · package.json
$ cnpm install cc.loader 
SYNC missed versions from official npm registry.


A JavaScript module loading/creation system for the web including support for baking. It includes support for asynchronously loading modules and their dependencies from multiple script files using a simple but powerful JavaScript API. It can optionally integrate with Joose to ease adding classes to modules or creating module files that are classes. cc.loader is written in CoffeeScript but supports JavaScript and CoffeeScript modules and compiles/bakes all CoffeeScript to JavaScript.


To install globally:

sudo npm install -g cc.loader


creating modules

To create a module with dependencies:

  .requires('module', 'other.submodule')
  .defines (function() {
    // code for this module, runs after required modules are loaded.

Each cc.loader module file must define a module name corresponding to its path otherwise the module will fail to load (but with a helpful error message). For example "other.submodule" must be defined in "other/submodule.js" or "other/". A configurable prefix which defaults to "lib" can also be prepended to the script path. Conversely when requiring a module as a dependency the filesystem path to load it from is determined from the module path.

Populating a module with cc.set:

// file must exist at <prefix>/friend/root.js based on the module name.
cc.module('friend.root').defines(function() {
  // Populating the JavaScript namespace corresponding to the module name
  // isn't mandatory, it is just a fairly sensible convention to use for
  // most modules and/or projects.
  cc.set('friend.root.favourite', 'cat');

  // You can populate any namespace from a module if you want.
  cc.set('friendly.Root.SayingsOf', { cat: 'meow', dog: 'woof' });

  // The namespace elements defined in this module will be available to the
  // `defines' callbacks of all including modules.
  var favourite = friend.root.favourite,
      catSays   =;

modules and namespaces

Each module has an associated JavaScript namespace with an identical name. There is no requirement for a module to populate this namespace but cc.loader provides simple mechanisms to do so if you want to use them.

The this object inside of the "defines" callback can be used to inject functions and variables into the JavaScript namespace associated with a module name:

cc.module('').defines(function() {
  // This makes available to all modules that require
  // Equivalent to: cc.set('', 'sleepy'); = 'sleepy';

  // Equivalent to this.sound = 'meow'.
  this.set('sound', 'meow');

  // Also works to set
  this.set('',   false);
  this.set('friend.human', true);

  // The "" namespace will only be created if "this"
  // contains at least one key, otherwise other mechanisms like cc.set can
  // be used to populate the module namespace and/or other namespaces.

Two modules split over two files:

// file: lib/pet/cat.js
cc.module('').defines (function() { = function(word) { console.log('mew' + word + 'mew'); }
// file: lib/root.js
cc.module('root').requires('').defines (function() {'prr');

  // this module elects not to use "this" and sets global variables manually. = "important string!!"

  // is a reference to the global "window" object in JavaScript, or
  // "global" under node.

Multiple modules can exist in a single file but only things defined by the module which has a name corresponding to the filesystem path are publicly available when "defines" callbacks of including modules are run.

loading modules

To use from html without baking:

<script type="text/JavaScript" src="cc/loader.js"></script>
<script type="text/JavaScript">
    cc.libpath = 'lib'; // URL to the folder containing all your modules.
                        // lib is the default.

    // assumes your module is at "lib/root/master.js". This will in turn load
    // all dependency modules and you will be able to debug them with their full
    // file paths.


When using cc.require or <script> tags one web request is made to load each script. Each request involves a potentially large set of replicated headers which slows down the load speed of the page. Installing cc.loader provides the "ccbaker" command which can be used to combine all modules reachable from a certain module file into a single (potentially minified/obfuscated) JavaScript file which can be loaded quickly.

To bake a module together with its dependencies and minify the output:

% ccbaker module.js > output.js

The root directory is determined from the name of the module in the first source file passed and where it sits in the filesystem tree. "hello.baker" at lib/hello/baker.js would set the root to "lib" but a module named "baker" at lib/hello/baker.js would set the root as "lib/hello".

Full arguments:

% ccbaker -h
ccbaker [arguments] <paths to source files>
    -c            compile CoffeeScript modules to JavaScript only
    -C            do not compile CoffeeScript to JavaScript
    -m            do not minify JavaScript
    -o            obfuscate JavaScript
    -s            use strict mode for packed file
    -w  [path]    output baked file to [path] and keep watching all reachable
                  paths for changes, recreating baked file as they change
    -v            print extra information to the terminal on stderr

e.g. Bake the modules reachable from two files without minifying the output:

% ccbaker -m primary.js > output.min.js

advanced usage

integration with joose

Joose is a object system for JavaScript. cc.loader provides some utility functions for creating Joose classes using the suggested namespace structure.

To create a Joose class under the module namespace:

cc.module('joose.root').defines (function() {
  this.jClass('Friend', {
    methods: {
      greet: function() { console.log("friendly greets"); }
  // equivalent to: cc.jClass('joose.root.Friend', ...)

  var friend = new joose.root.Friend();

A module itself can be a Joose class:

// file: lib/root/Enemy.js
  // The module is the Joose class. I start these files with a capital letter
  // but it isn't mandatory.
  methods: {
    greet: function() { console.log("angry greets"); }

An alternative way of making a module that is a Joose class:

// file: lib/root/Boss.js
cc.module('joose.Boss').requires('joose.Enemy').defines(function() {
  // uses this.jClass as it must be postponed until after joose.Enemy has loaded
  // in order for the inheritance to work.
    isa: joose.Enemy,
    override: {
      attack: function() {
        console.log("throw hammer");
        console.log("breath fire");

Shorthand to create a module class that inherits another:

// file: lib/root/EndBoss.js
  // isa: joose.Boss, // not necessary, handled by .parent(...)
  after: {
    attack: function() {
      jconsole.log("special attack");
      jconsole.log("is the princess");
// file: lib/root.js
cc.module('root').requires('root.EndBoss').defines (function() {
  this.jClass('Friend', {
    methods: {
      greet: function() { console.log("friendly greets"); }

  var friend = new root.Friend(),
      enemy  = new joose.EndBoss();


hooking in your own class system

cc.module('Cat').defines(function() { // "extend" can be used to hook your own class system in self.set('extend', function(class) { class.catlike = true; return class; }) })

// Since the parent namespace "Cat" defines "extend", then HouseCat is set to // the return value of Cat.extend(<argument to jClass>) // In this case defining: // HouseCat.catlike = true // HouseCat.playful = true cc.module('HouseCat').parent('Cat').jClass({ playful: true })

empty modules

A module doesn't have to have a "defines" call but if not it must call "empty". This can be useful for creating modules that serve only to bundle other modules together:

cc.module('util').requires('util.file', 'util.path').empty();

module that is a function

// This module only defines a function at the corresponding namespace.
cc.module('some.function').func(function() {

notes on development

IE makes it very difficult to reliably determine whether a script has loaded without polling, so you will not see errors indicating module load failures until after a 10 second or so delay. For this reason developing your module structure under IE is not recommended. Once the module structure works then debugging code under IE with full path names should be as easy as in a decent browser.

The poll timeout can be set with the following code and should be set before requiring the first module:

cc.ieScriptPollTimeout = 5000; // in milliseconds, 5000 is the default

The reason every file requires a module corresponding to the filename is to support IE 8 and below.


  • baker: node.js, npm will fetch other node module dependencies for you.
  • web: nothing to use the library or a baked library. If Joose is loaded then a small amount of extra API is available.


% git clone git://
% cd cc.loader
% npm test
cc.loader test server listening on: 8012
please go to http://localhost:8012/


  • What does the name mean? I like C.C. Lemon
  • Why not RequireJS? - RequireJS supports a lot of things, but has a large manual so it can be perceived as rather difficult to use. I prefer to use the namespacing system cc.loader provides over assigning every dependency to a variable as in RequireJS.

Current Tags

  • 1.3.0                                ...           latest (8 years ago)

7 Versions

  • 1.3.0                                ...           8 years ago
  • 1.2.1                                ...           8 years ago
  • 1.1.1                                ...           8 years ago
  • 1.1.0                                ...           8 years ago
  • 1.0.1                                ...           8 years ago
  • 1.0.0                                ...           8 years ago
  • 0.18.0                                ...           8 years ago
Maintainers (1)
Today 0
This Week 0
This Month 0
Last Day 0
Last Week 0
Last Month 0
Dependencies (4)
Dev Dependencies (2)
Dependents (2)

Copyright 2014 - 2017 © |