Sea.js Manual & Documentation


Table of Contents


Module Definition

In SeaJS, any JavaScript file should be written in module format, and files and modules are in one-to-one correspondence.

define

A global function "define" is available to define modules. The signature of this function is:

define(id?, dependencies?, factory);

id

The unique identifier for the current module. This argument is optional, and if it is not present, the loader will set the module id to the request uri of this module file. When present, the module id MUST be a top-level or absolute id (relative ids are NOT allowed).

dependencies

The module’s dependency array which is an array of module identifiers. This argument is optional. If it is not present, the loader will parse the factory.toString() to extract the dependency.

** NOTICE: It is highly recommended to ignore the id and dependencies arguments in the define statement. The optimization tool will generate these arguments automatically in the deployment phase.

factory

A function that will be executed only once to initialize the module. In addition to a function, the factory argument can also be an object, a string, or any other value, and in those case, the module exports are set to the factory value directly.

Three symbols are available in the function body of factory to every module: require, exports, and module.

define(function(require, exports, module) {

  // The module code goes here
  
});

exports

The exports object is used to export the API of the module.

define(function(require, exports) {
  // snip...
  exports.foo = 'bar';
  exports.doSomething = function() {};
});

Except adding members to the exports object, you can also use return to provide the API directly.

define(function(require) {
  // snip...
  return {
    foo: 'bar',
    doSomething: function() {};
  };
});

If the return statement is the only code in the module code, it can be simplified to:

define({
  foo: 'bar',
  doSomething: function() {};
});

The above authoring format is especially suited for defining JSON data.

** ATTENTION: The following code DOES NOT work!

define(function(require, exports) {
  // snip...
  exports = { // WRONG!
    foo: 'bar',
    doSomething: function() {};
  };
});

The module loader cannot obtain the new value assigned to the exports variable. Please use return or module.exports to expose the API in this case.

require

The require function is used to access the exported API of foreign modules.

define(function(require) {
  var a = require('./a');
  a.doSomething();
});

It accepts a single module identifier as parameter.

Keep in mind that you'll need to follow a few simple rules to make sure that static analysis will be able to detect the dependencies within your module in the development phase.

require.async

Use this function to load the specified modules asynchronously and execute the optional callback when complete.

define(function(require, exports) {
  // load one module
  require.async('./b', function(b) {
    b.doSomething();
  });
  
  // load multiple modules
  require.async(['./c', './d'], function(c, d) {
    // do something
  });
});

require.resolve

Use the internal require() machinery to look up the location of a module, but rather than loading the module, just return the resolved uri.

require.load

Use this function to fetch the specified uris asynchronously and execute the optional callback when complete. You can override this function to implement custom fetching method.

require.constructor

Occasionally, we want to add some members to the require argument in all module factories. In this case, using require.constructor is very convenient.

module

The module object contains metadata about the module. It contains the following members:

module.id

The unique identifier for the current module. require(module.id) must return this module’s exports object.

define(function(require, exports, module) {
  console.log(module.id); // http://path/to/this/file.js
  console.log(require(module.id) === exports); // true
});

module.dependencies

module.dependencies is a reference to the module’s dependency array.

This array is informative only: modification of this array has no effect on the module once the module has been provided to the environment.

module.exports

The exports object is created by the module system. Sometimes this is not acceptable, many want their module to be an instance of some class. To do this assign the desired export object to module.exports.

define(function(require, exports, module) {
  console.log(module.exports === exports); // true
  module.exports = new SomeClass();
  console.log(module.exports === exports); // false
});

Note that assignment to module.exports must be done immediately. It cannot be done in any callbacks. This does not work:

x.js:

define(function(require, exports, module) {
  setTimeout(function() {
    module.exports = { a: "hello" };
  }, 0);
});

y.js:

define(function(require, exports, module) {
  var x = require('./x');
  console.log(x.a); // undefined
});

module.constructor

Occasionally, we want to add some members to all module objects. In this case, using module.constructor is very convenient.

extend.js:

define(function(require, exports, module) {
  var Module = module.constructor;

  Module.prototype.filename = function() {
    var id = this.id;
    var parts = id.split('/');
    return parts[parts.length - 1];
  };
});

a.js:

define(function(require, exports, module) {
  exports.filename = module.filename();
});