Module Lookup

It's important to understand the path lookup behavior of modules.

Path Lookup Behavior of the Require Method

B2C Commerce's method has different lookup behavior than the require() function, as specified in the Modules 1.1.1 CommonJS specification.

Path Lookup Relative to the Current Module

If the path argument starts with "./" or "../", then it loads relative to the current module. The module can be a file or a directory. A file extension is acknowledged, but not required. If it's a directory, a package.json or a main file is expected in the directory.


A main file is a file named main, with either a .js, .ds, or .json extension.

If the package.json file does not contain a main property, the script defaults to the main file in the directory, if one exists. Access to parent files can't go beyond the top-level version directory. Access to other cartridges is allowed.

Path Lookup Relative to the Current Cartridge

If the path argument starts with "~/", then it's a path relative to the current cartridge. This path is relative to the top level of the current cartridge.

You can use this pattern to reference a script in the current cartridge. In SFRA, this pattern is only used for scripts that you don't want others to extend or override.

var myscript = require('~/cartridge/scripts/myscript');

Path Lookup Relative to The Start of the Cartridge Path

If the path argument starts with "*/", then it's a path relative to the start of the cartridge path. This pattern is used in all require statements in the app_storefront_base cartridge.

For example, assume the following cartridge path:


Assume that you want to extend the Stores.js controller in the base cartridge, which requires the storeHelpers.js script.

var StoreHelpers = require('*/cartridge/scripts/helpers/storeHelpers');
var server = require('server');
var cache = require('*/cartridge/scripts/middleware/cache');

Assume also that the plugin_stores cartridge extends the storeHelpers.js script.

If you create a custom Stores.js controller, and you require or extend the Stores.js controller, the asterisks are in the base controller are important. They indicate that the storeHelpers.js script from the plug-in cartridge is used, if available, instead of the version in the base cartridge. Whichever version is the first one found on the cartridge path is used. In other words, whichever version is furthest to the left of the cartridge path is used.

Path Lookup of a B2C Commerce Script Package

A path argument that prepends "dw", or that starts with "dw/", references B2C Commerce built-in functions and classes, for example:
 var u = require( 'dw/util' );
This statement loads the classes in the util package, which can be then used as follows:
var h = new u.HashMap();

Path Lookup of a Top-Level Module

A path argument that doesn't start with "./" or "../" is resolved as top-level module.
  • The path argument is used to find a folder in the top-level version directory, typically a cartridge itself, but it can also be a simple folder.
  • If nothing is found, the path argument is used to look into a special folder (named modules) in the top version directory. You can use this folder to manage different modules. For example, you can drop a module like express.js into that folder.
If the method is used to reference a file, an optional file extension is used to determine the content of the file. Currently, B2C Commerce supports these extensions, listed in priority order:
  • .js - JavaScript file
  • .ds - B2C Commerce script file
  • .json - JSON file
Note: If you use JSON to define a module, the entire JSON object is implicitly exported via the exports variable.
Note: You can still use the importScript and importPackage methods. However, we recommend that you replace them with the method.

Example: Path Lookup for Global Mymodule.Js

Assume you have a script (used in SFRA) with the following call to the require() method:
var u = require( 'mymodule');

Because there's no path syntax, this statement is requiring a global module. In this case, it's requiring the mymodule module.

Assume the following project structure on your developer machine:
  ├── bin
  ├── cartridges
      ├── app_storefront_base
      │   └── cartridge
      │       ├── client
      │       ├── controllers
      │           └── mymodule.js
      │       ├── forms
      │       ├── models
      │           └── mymodule.js
      │       ├── scripts
      │       ├── static
      │       └── templates
      └── modules
          └── server
      └── mymodule
          ├── myScript.ds 
          ├── package.json              
          └── main.js   
      └── mymodule.js
After upload, these files have the following structure on the server:
    └──mymodule.js        (2)
    ├───modules                         // Global modules directory
    │     └── mymodule.js  (3)
    ├───mymodule                        // Module Library directory
    │     ├── myScript.ds  (1b)
    │     ├── package.json (1a)         // References myScript.ds
    │     └── main.js                   
    ├───app_storefront-base             // Cartridge directory
          └── controllers 
          │  └── mymodule.js  
          └── models 
              └── mymodule.js  

This structure includes directories and files that are outside of cartridges. These files and directories don't have to be on the cartridge path to be accessible.

Regardless of where the script that requires a module is located, B2C Commerce finds the module as follows:
  1. B2C Commerce searches the mymodule directory for a package.json file.
    1. In this example, the package.json is present, so B2C Commerce checks the value of the main property in the file.
    2. This property references the myScript.ds file, so B2C Commerce loads myScript.ds as a module.
    3. If there is no package.json or if the main property is missing, B2C Commerce searches the directory for a main file to load.
    4. If B2C Commerce finds a main file, the file is loaded; otherwise, B2C Commerce continues to search.
  2. B2C Commerce finds the mymodule.js file because it's in the top-level version directory. If there is no file at this level, B2C Commerce continues to search.
  3. B2C Commerce searches the modules directory in the top level for a mymodule script file.
Note: The mymodule.js files inside the cartridge are not searched at all, because they are not global modules.

While B2C Commerce provides a sophisticated fallback mechanism for scripts in the globally available modules folder, we generally discourage polluting the global namespace with utility scripts. Instead, we recommend that you add scripts to specific project cartridges.

X Privacy Update: We use cookies to make interactions with our websites and services easy and meaningful, to better understand how they are used. By continuing to use this site you are giving us your consent to do this. Privacy Policy.