RequireJS in Commerce
This topic describes general concepts of how the RequireJS library is used in Magento, with examples. Please refer to official RequireJS documentation for in-depth explanation.
RequireJS is a JavaScript file and module loader. It improves perceived page load times because it allows JavaScript to load in the background. In particular, it enables asynchronous JavaScript loading.
RequireJS configuration in Magento
All configuration is done in the requirejs-config.js
file. It has a single root object config
which contains the configuration options described below. All the configuration settings are optional and are used only when required. The following snippet is a sample requirejs-config.js
describing the structure of the file. Example requirejs-config.js
file
1
2
3
4
5
6
7
8
9
10
var config = {
map: {...},
paths: {...},
deps: [...],
shim: {...},
config: {
mixins: {...},
text: {...}
}
}
map
The map
configuration maps (connects) any real AMD modules that calls define()
, to the specified alias. In the snippet below, *
means all loaded RequireJS modules can use the specified alias. The second mapping applies only in the context of Vendor_Module/js/amd-module
. So, both types of contexts can be applied: either a global context, or a module specific context.
1
2
3
4
5
6
7
8
map: {
'*': {
alias: 'Vendor_Module/js/complex/path/amd-module'
},
'Vendor_Module/js/amd-module': {
alias-two: 'Vendor_Module/js/complex/path/amd-module-two'
}
}
Now we can use our Vendor_Module/js/complex/path/module
using alias
in any RequireJS module or config file without needing to type the entire path. For example, in Magento, catalogAddToCart
is mapped to Magento_Catalog/js/catalog-add-to-cart
and can be used anywhere as a RequireJS module name. In the next example, catalogAddToCart
is mapped to Magento_Catalog/js/catalog-add-to-cart
only in the context of the discountCode
module.
1
2
3
4
5
6
7
8
map: {
'*': {
catalogAddToCart: 'Magento_Catalog/js/catalog-add-to-cart'
},
'discountCode': {
catalogAddToCart: 'Magento_Catalog/js/catalog-add-to-cart'
}
}
You can also use the map
configuration to override a JS module with a custom JS module. See Custom JS component.
paths
The paths
configuration, similar to map
, is used for aliasing not just any real AMD module that calls define()
, but also any JS file (even from a URL), HTML templates, etc. Magento uses this to alias URLs and third party libraries.
1
2
3
4
paths: {
'alias': 'library/file',
'another-alias': 'https://some-library.com/file'
}
When setting a path to an array with multiple script sources, if the first script fails to load, the next is used as a fallback.
1
2
3
4
5
6
7
8
9
var config = {
...
paths: {
'alias': [
'https://some-library.com/file',
'vendor_name>_<module_name>/js/file'
]
}
};
For external content, resources should be whitelisted; otherwise Magento raises error notices in the browser console. See Content Security Policies.
Consider the example of overwriting an HTML file in the adminhtml.
In this example, the max-length
value of the text-box in the adminhtml
is altered. The HTML file is located at vendor/magento/module_ui/view/base/web/templates/form/element/input.html
.
-
Create a
requirejs-config.js
file underapp/code/<Vendor_Name>/<Module_Name>/view/base/
and add the following code:1 2 3 4 5
var config = { paths: { 'ui/template/form/element/input': '<vendor_name>_<module_name>/template/form/element/input' } };
- Create an
input.html
file underapp/code/<Vendor_Name>/<Module_Name>/view/base/web/template/form/element/
and copy the contents of theinput.html
file from themodule_ui
template file. - Change the maxlength value to
512
, which was originally set to256
. -
Upgrade the Magento application:
1
bin/magento setup:upgrade
-
Generate the dependency injection configuration:
1
bin/magento setup:di:compile
- Confirm the modification by inspecting the element source code and check the
maxlength
value, which should be512
as specified in the template.
The path for Magento_Ui/templates
is set to be ui/template
in the requirejs-config.js
module of module_ui
, hence ui/template
is used for specifying the path. If no paths are set, <module_name>/templates
should be used.
deps
The deps
configuration is used to add a dependency. It can either be used directly under var config = {}
or under a shim configuration. Adding modules under an independent deps
configuration will load the specified modules in all pages.
In this snippet, the custom Vendor_Module/js/module
will be loaded in all pages.
1
deps: ['Vendor_Module/js/module']
shim
The shim
configuration is used to build a dependency on a third party library, since we cannot modify it.
When to use the shim
configuration:
- To add a new dependency to a third party library
- To add a new dependency to a third party library which does not use an AMD module
- To change load order by adding a dependency to a third party library
In this snippet, dependencies are added directly in an array, or it can be specified as an array under the deps
key. The exports
key is used to specify under what identifier the module is exported into. This export identifier can be used to access it.
1
2
3
4
5
6
7
shim: {
'3rd-party-library': ['myJSFile'],
'another-3rd-party-library': {
deps: ['myJSFile'],
exports: 'another3rdPartyLibrary'
}
}
mixins
The mixins
configuration is used to overwrite component methods of an AMD module which returns either a UI component, a jQuery widget, or a JS object. Unlike the above configuration properties, the mixins
property is under the config
property, apart from the parent object called config.
In this snippet, Vendor_Module/js/module-mixin
will overwrite the existing component methods in Vendor_Module/js/module
with the specified component methods. It is a convention to name the mixin by appending a -mixin
to the original path/to/js
, although not required.
1
2
3
4
5
6
7
config: {
mixins: {
'Vendor_Module/js/module': {
'Vendor_Module/js/module-mixin': true
}
}
}
The concept of Javascript mixins itself is explained in depth in Using Javascript Mixins.
text
The text
configuration is used to set the security request headers using the text.js
file.
Without Cross Origin Resource Sharing (CORS) it is not possible to add the X-Requested-With
header to a cross domain XHR request. Set this header to tell the server that the request was initiated from the same domain.
1
2
3
4
5
6
7
config: {
text: {
'headers': {
'X-Requested-With': 'XMLHttpRequest'
}
}
}