Controllers
Controllers are server-side scripts that handle storefront requests. Controllers manage
the flow of data in your application, and create ViewModels
to process each
storefront request as a route
and generate an appropriate response. For
example, in a storefront application, clicking a category menu item or entering a search term
triggers a controller that renders a page.
Controllers are written in JavaScript and Salesforce B2C Commerce script. They must conform to the CommonJS module standard.
A controller's file extension can be either .ds or .js. Controllers must be located in the
controllers
folder at the top level of the cartridge. Exported methods
for controllers must be explicitly made public to be available to handle storefront
requests.
Example: SFRA Base Cartridge Controller Hello.Js
'use strict';
var server = require('server');
var cache = require('*/cartridge/scripts/middleware/cache');
server.get('World', cache.applyDefaultCache, function (req, res, next) {
res.render('helloworld', {
Message: 'Hello World! Again.'
});;
next();
});
module.exports = server.exports();
require
to: - Import script modules. Any B2C Commerce script can be made into a CommonJS module and required by a controller.
- Import B2C Commerce packages, instead of using the importPackages method.
This approach is the recommended way to reference functionality from a controller. You
can also use the require method to import a single B2C Commerce class. For example:
var rootFolder = require('dw/content/ContentMgr').getSiteLibrary().root;
While it isn't best practice, controllers can also:
- Call other controllers. We don't recommend that controllers call each other, because controller functionality is self-contained to avoid circular dependencies. Sometimes, however, such as calling non-public controllers during the checkout process, it's unavoidable.
- Call pipelets. We strongly discourage calling pipelets from within a controller. However, it's allowed while there are still pipelets that don't have equivalent B2C Commerce script methods.
- Import packages. We discourage this approach because it doesn't use standard JavaScript patterns. This approach is Rhino-specific.
- Call pipelines that don't end in interaction continue nodes. This technique is only
intended for use with existing link cartridges and is highly discouraged for general
development. Note: It isn't currently possible to call pipelines that end in interaction continue nodes.
Request URLs
controller-function
. For
example, the request URL for the Hello.js controller World function looks like:
https://localhost/on/demandware.store/Sites-RefArch-Site/default/Hello-World
Reserved Names for Controllers
B2C Commerce has several system names that are reserved and can't be used for custom controllers and their functions. For a full list, see System Pipelines and Controllers.
Global Variables, Request Parameters, and Page Meta Data
SFRA uses the server.req
and server.res
objects for
request and response data. While global variables are still available, we don't recommend
that you use them.
Debugging
Almost any JavaScript-related error gets logged in the
customerror_* log
files, including errors from B2C Commerce scripts and
controllers. The error_*
log files contain Java-related errors on B2C
Commerce, and are probably less useful to non-B2C Commerce employees
Error.js
controller services uncaught errors. By default, B2C Commerce
returns a 410 error, which indicates that the resource is no longer available. If you prefer
404, it's fine to use as long as the related ISML template doesn't include
<isslot>
, <iscomponent>
, or
<isinclude>
tags. When you want to handle these errors explicitly,
you can use try/catch
statements.
Best Practices
Performance
Only require modules when you need them, not at the top of a module.
Using with OCAPI
You can build a mobile or native app in addition to your storefront. If you want to create modules that work both for a desktop storefront and a mobile app, use hooks.