# SFRA Modules

Access JavaScript/B2C Commerce script modules that conform to the Modules 1.1.1 CommonJS specification within your storefront script code.

For information about the Modules 1.1.1 CommonJS specification, see [Modules 1.1.1](http://wiki.commonjs.org/wiki/Modules/1.1.1).

- [CommonJS Modules and Require](/docs/commerce/b2c-commerce/guide/b2c-sfra-modules.md#commonjs-modules-and-require)
- [ImportPackage vs. Require](/docs/commerce/b2c-commerce/guide/b2c-sfra-modules.md#importpackage-vs-require)

## CommonJS Modules and Require

Use CommonJS modules to share reusable functionality. Multiple controllers can reuse the same module.

A module is a `.ds` or `.js` file. You put module files either in the special `modules` folder or in a cartridge’s `script` folder.

The `modules` folder is a peer of cartridge folders. B2C Commerce provides it for globally shared modules, such as third-party modules.

```
+-- modules
    +-- mymodule1.js
+-- My_Cartridge_1
    +-- cartridge
        +-- scripts
            +-- mymodule2.js
+-- My_Cartridge_2
    +-- cartridge
        +-- scripts
            +-- mymodule3.js

```

Access modules in your cartridge, in other cartridges, or in the `modules` folder.

Storefront Reference Architecture (SFRA) provides a `server` module in the modules folder. This name is reserved for this module and editing the `server` module voids any promise of backward compatibility or support from B2C Commerce.

## Accessing Modules

B2C Commerce supports CommonJS `require` syntax to access modules and relative paths.

Use this syntax:

| Syntax | Use                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | Example                                            |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| ~      | Specifies the current cartridge name.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | `require ('~/cartridge/scripts/cart')`             |
| .      | Specifies the same folder (as with CommonJS).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | `require('./shipping');`                           |
| ..     | Specifies the parent folder (as with CommonJS).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | `require('../../util')`                            |
| */     | Searches for the module in all cartridges that are assigned to the current site from the beginning of the cartridge path. The search is done in the order of the cartridges in the cartridge list. This notation makes it easier to load modules for a logical name. You don't have to remember what cartridge is the first in the cartridge path for a site to contain the module. For example, you can have multiple plug-in cartridges that each have a copy of the module. This syntax lets you add new plug-ins and always use the module that is first in the cartridge path. | `var m = require('*/cartridge/scripts/MyModule');` |

## ImportPackage vs. Require

Use `ImportPackage` statement to import B2C Commerce packages into scripts used by pipeline script nodes.

However, we recommend that you use `require` to import B2C Commerce script packages instead of `ImportPackage`. For example: `require(‘dw/system/Transaction’)`

:::important
Using the `require()` function to load a module has an impact on performance. To handle a request, a controller is loaded and then executed on a *global level*, just as exported methods are executed. When the controller module is initialized, the actual controller function is invoked.

If the dependencies to other modules are initialized on a global level, many modules can be loaded unnecessarily. If possible, place `require()` statements in the most limited scope that is appropriate (for example, as local variables within a function body). If your `require()` statements are placed at a global level, they are loaded for every request. For example, `require()` statements at the top of a controller file are loaded with each request. Globally required modules are loaded even if they are not needed in the current execution context.

If all modules execute their `require()` statements globally, all modules are loaded for every request. This overhead can significantly degrade performance, depending on the number of modules. We suggest, instead, that you move the `require()` calls for non-API modules into the function bodies so that they are resolved only when necessary. A `require()` isn't an import; it's a real function call. An import in Java, in contrast, is only a compiler directive and has no effect at run time.
:::

## Understanding Cartridge Path Inheritance for Controllers and Pipelines

When a request arrives for a specific URL:

1. B2C Commerce searches the cartridge path for a matching controller. If the controller is found, it's used to handle the request.
2. If no controller is found, the cartridge path is searched again for a matching pipeline. If the pipeline is found, it's used to handle the request.

:::note
If a cartridge contains a controller and a pipeline with a matching name, the controller takes precedence.
:::

When searching the cartridge path, B2C Commerce doesn't verify whether the controller contains the called function in the requesting URL. Calling a controller function that doesn't exist causes an error.

The platform simply searches the `controllers` folder. Therefore, it doesn't matter what type of cartridge contains the controllers. They can be in a SiteGenesis JavaScript Controllers (SGJC) cartridge or a Storefront Reference Architecture (SFRA) cartridge.

## Inheriting and Overriding Modules in Your Cartridge Stack Using Module.SuperModule

Often, you can have several layers of cartridges that overlay one another. Each cartridge can import from the previous cartridge and overlay it. To make this easy, B2C Commerce provides a chaining mechanism that lets you access modules that you intend to override.

The `module.superModule` global property provides access to the most recent module on the cartridge path module with the same path and name as the current module.

![Diagram showing how module.superModule accesses the most recent matching module in the cartridge path](https://a.sfdcstatic.com/developer-website/sfdocs/commerce-cloud/media/sfra/b2c_sfra_super_module.gif)

B2C Commerce searches cartridges after the current cartridge on the site cartridge path. It searches for a module with the same name and in the same location in the cartridge as the current module. B2C Commerce skips cartridges before the current cartridge in the path, and it skips the current cartridge, and only searches cartridges after the current cartridge. It continues searching through all the remaining cartridges in the cartridge path until a matching module is found. If no matching module is found, `module.superModule` returns `null`.

:::note
To create a module that inherits from an existing module, create the existing module in your cartridge and require it in your new module. For example, suppose that you want to create a home page for a specific customer group, named `BigSpenderHome.js`. To create the homepage, first create `Home.js` in your cartridge. Next, modify it to include (require) the functionality of `Home.js` from your cartridge stack.
:::

### Example: Overriding and Extending an Existing Controller

This example shows how the Page.js module is inherited from the last cartridge in the stack and overrides the Show function. Specifically, it changes the data model used to render the page to show *Hello B2C Commerce.*

```
//Page.js
var page = module.superModule; // require functionality from last controller in the chain with this name
var server = require('server');

server.extend(page);

server.append('Show', function(req, res, next) {
    res.setViewData({ value: 'Hello B2C Commerce' });
    next();
});

module.exports = server.exports();
```

## SuperModule Scenarios

For example, suppose that you are modifying the `Page.js` file, and it defines a `page` variable using the `module.superModule` property:

```
//Page.js
var page = module.superModule;
```

The `Page.js` file is located in the folder `mysite/cartridges/cartridge_B/cartridge/controllers`.

Suppose that you have the following cartridge path:

```
cartridge_A: cartridge_B: cartridge_C: cartridge_D: app_storefront_base
```

B2C Commerce searches the path starting with `cartridge_C`.

| If:                                                                                                                                                      | The platform returns:                                                                                  |
| -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| All cartridges contain a `Page.js` file in the same location as `cartridge_B`.                                                                           | `cartridge_C module` `Page.js` module- because it's the next cartridge after `cartridge_B` in the path |
| `cartridge_A` and `cartridge_D` contain a `Page.js` file in the same location as `cartridge_B`.                                                          | `cartridge_D module` `Page.js` module - because it's after `cartridge_B` in the path                   |
| Only `cartridge_A` contains a `Page.js` file in the same location as `cartridge_`B.                                                                      | `null` - because `cartridge_A` isn't after cartridge_B in the path                                     |
| All cartridges contain a Page.js file in a different location than cartridge_B.                                                                          | `null` - because none of the files match the location of the file in the current cartridge.            |
| `cartridge_C` contains a `Page.js` file in a different location and app_storefront_base contains a `Page.js` file in the same location as `cartridge_B`. | `app-storefront_base` `Page.js` module - because the files must match name and location.               |

The power of the `module.superModule` mechanism is that it lets you chain overlay cartridges on top of one another. For example, if `cartridge_C` and `cartridge_D` both use the `module.superModule` function and both add functionality, all of that functionality is available to `cartridge_B`.

:::important
Chaining depends on an expected order of cartridges in the site cartridge path. Therefore, changing the order of cartridges in the cartridge path can impact your code. To minimize code changes, think about the order of your cartridge layers in advance.
:::

## Global Modules

Make a script globally available by adding it to the `modules` folder. We recommend that you add the script to the `storefront-reference-architecture` repository’s `modules` folder. We recommend a single `modules` directory in one repository per site. This approach makes upload work in a predictable manner. The `uploadCartridge` tool deletes the existing `modules` folder before upload, and the `upload` tool doesn't identify or prevent naming collisions when uploading files.
