• typedef


A Loader-unique string that represents a module.

The moduleName is a string that serves as the canonical name for a module. It is used as the key in the module registry.

In Steal, as with most module loaders, each module is only loaded (executed) once even if it is being imported by dozens of other modules. In order to provide importing modules with the correct exported values Steal has a module registry; an object where the moduleName is the key and the value is metadata about the module, as well as it's exported value.

When a module imports another, such as require("./foo") the string used to import is called a moduleIdentifier. This identifier is then normalized which produces the canonical moduleName.

moduleName vs moduleIdentifier

It's important to understand the difference between a moduleName and moduleIdentifier. A moduleIdentifier is the string that is provided to the import, require(), (or any other format) statements. For example:

Module identifierModule name

These identifiers are always relative to the current module. For example the import:

import "./foo";

When the current module is app/main will normalize to app/foo and is located at baseURL + app/foo.js.

Similarly npm packages are also normalized relative to their parent. Consider this:

import _ from "lodash";

If the parent module, app/main has an npm dependency on the lodash package then this will normalize to lodash@1.0.0#main and the address will be something like

However, if the parent module does not have an npm dependency on lodash then the moduleName will be lodash and the address something like

npm module names

When importing modules installed with npm the moduleName normalizes to something like lodash@1.0.0#main. While strange looking this form has a purpose. Remember that each moduleName in the registry must be unique. npm packages, however, are not, and nested dependencies can use different versions of the same package. When this happens it's important that each module gets a semver compatible version of the package they need.

Here are the parts of an npm moduleName, using lodash@1.0.0#main:


The first part is the packageName, lodash. It is the string that you provide when installing the package like npm install lodash --save.


The second part, between the @ and the # is the package version, in this case it is 1.0.0. Steal ensures that you get a semver compatible version of a package.

Consider there are two dependencies in your project that both depend on the foo package. One of their package.jsons looks like:

  "dependencies": {
    "foo": "^1.0.0"

And the other like:

  "dependencies": {
    "foo": "^1.1.0"

Both of these packages depend on foo, however the second depends on a higher version, ^1.1.0. The ^ symbol means that it depends on at least that version, and can accept anything up to (but not including) 2.0.0. See the semver calculator to better understand the versioning rules.

Since both packages depend on foo and and 1.1.0 is semver compatible with ^1.0.0 then both will receive the same version of the package. import "foo" will resolve to a module name like:



The last part of the npm moduleName is the modulePath. The modulePath is the part that comes after the # symbol. With the lodash example the modulePath is main. The modulePath is used to know where the module is located within the package. Here it will be at

You can import paths within a package, not just the package's main. To do that you might import: import each from "lodash/arrays/for_each". This module's moduleName would be lodash@1.0.0#arrays/for_each and it's address

Help us improve StealJS by taking our community survey