This specification establishes a convention for creating a style of reusable JavaScript modules and systems that will load and link those modules.
- Modules are singletons.
- Modules have an implicitly isolated lexical scope.
- Loading may be eager in asynchronous loaders.
- Execution must be lazy.
- With some care, modules may have cyclic dependencies.
- Systems of modules may be isolated but still share the same context.
- Modules may be used both in browsers and servers.
- A module must only read and write variables in its lexical scope.
- A module must only assume that its lexical scope contains the free
variables
require
,module
,exports
, anddefine
beyond those defined by JavaScript. What constitutes JavaScript is beyond the scope of this specification and may vary with practical limits on a module's portability. - A module must only depend on specified behavior of the values provided to its lexical scope.
- All calls to
require
must be by name from lexical scope. - All calls to
require
must be given a single string literal as the argument. - For interoperability with loaders that support the following cases,
modules must call
define
in their first and only module scope statement.- When modules must be debugged when deployed on a different domain than the origin page (perhaps a CDN) in browsers that do not support cross-origin HTTP request headers (CORS) or the developer cannot configure the deployment server to provide CORS headers. JavaScript that is deployed in a debuggable form will suffer performance penalties since it would preclude minification and bundling.
- modules must be debugged in browsers that do not support
//@sourceURL
comments and (a module build step or module server that adddefine
calls are not acceptable).
- Within a
define
callback
, the variablesrequire
,exports
, andmodule
must use the corresponding values provided as arguments to the callback instead of those received from lexical scope. - The first argument,
require
, to adefine
callback
must be namedrequire
.
- The top scope of a module must not be shared with any other module.
- A
require
function must exist in a function's lexical scope.- The
require
function must accept a module identifier as its first and only argument. require
must return the same value asmodule.exports
in the identified module, or must throw an exception while trying.require
may have amain
property.- The
require.main
property may be read-only and non-configurable. - The
require.main
property must be the same value asmodule
in the lexical scope of the first module that began executing in the current system of modules. - The
require.main
property must be the same value in every module.
- The
require
must have aresolve
function.resolve
accepts a module identifier as its first and only argumentresolve
must return the resolved module identifier corresponding to the given module identifier relative to this module's resolved module identifier.
- The
- an
exports
object must exist in a function's lexical scope.- the
exports
object must initially be the same value asmodule.exports
.
- the
- A
module
object must exist in a function's lexical scope.- The
module
object must have anid
property.- The
module.id
property must be a module identifier such thatrequire(module.id)
must return themodule.exports
value when called in this or any module in the same system of modules. - The
module.id
property may be read-only and non-configurable.
- The
- The
module
object must have anexports
property.- The
module.exports
property must initially be an empty object. - The
module.exports
property must be writable and configurable.
- The
- The
module
object may have apath
URL relative tofile:///
- The
module
object may have adirectory
URL relative tofile:///
- The directory must be the directory containing the
path
.
- The directory must be the directory containing the
- The
- a
define
function must exist in a function's lexical scope.define
accepts a function ("callback") as its last argument.callback
acceptsrequire
,exports
, andmodule
.callback
must be called with the corresponding values from the module's lexical scope.- If
callback
returns a value other thanundefined
, the return value must be assigned tomodule.exports
.
- A module identifier is a string of "terms" delimited by forward slashes.
- A term is either:
- any combination of lower-case letters, numbers, and hyphens,
.
, or..
- Module identifiers should not have file-name extensions like
.js
. - Module identifiers may be "relative" or "resolved". A module
identifier is "relative" if the first term is
.
or..
. - Top-level identifiers are resolved relative to
""
. - The
require
function in each module resolves relative identifiers from the correspondingmodule.id
. - To resolve any path of module identifiers,
- An array of terms must be initialized to an empty array.
- For each module identifier in the path of identifiers,
- Pop off the last term in the array, provided one exists.
- For each term in a module identifier in order,
- Take no action if the term is
"."
. - Pop a term off the end of the array if the term is
".."
. - Push the term on the end of the array otherwise.
- Take no action if the term is
- The array of terms must be joined with forward slashes,
"/"
to construct the resulting "resolved" identifier.
This specification leaves the following important points of interoperability unspecified:
- Whether modules are stored with a database, file system, or factory functions, or are interchangeable with link libraries.
- Whether a path is supported by the module loader for resolving module identifiers.
- Whether other arguments may be provided to
define
and how they are interpreted.