JavaScript
Magento 2 makes use of quite a large number of JavaScript libraries, shown as follows:
- Knockout: http://knockoutjs.com
- Ext JS: https://www.sencha.com/products/extjs/
- jQuery: https://jquery.com
- jQuery UI: https://jqueryui.com
- modernizer: http://www.modernizer.com
- Prototype: http://www.prototypejs.org
- RequestJS: http://requirejs.org
- Script.aculo.us: http://script.aculo.us
- moment.js: http://momentjs.com/
- Underscore.js http://underscorejs.org
- gruntjs: http://gruntjs.com
- AngularJS: https://angularjs.org
- jasmine: http://jasmine.github.io
- …
The RequireJS and jQuery libraries are probably the most interesting ones, as they often step into the spotlight during frontend development. RequireJS plays a big role in magento 2, as it loads other JavaScript files. Using a modular script loader like RequireJS improves the speed of code.
JavaScript resources can be found at following location in the Magento 2 Systemt:
- Libarry level for all libraries in the Magento code base (lib/web).
- Module level for all libraries in a module (app / code / {vendorName} / {moduleName} / view / {area} / web)
- Theme for all libraries in a theme (app / design / {area} / {vendorName} / {theme} / {vendorName}_{moduleName}/web)
It is recommended to specify JavaScript resources in the templates rather than in the layout updates. This way, we ensure processing of the resources through RequireJs.
To work with the RequireJS library, specify the mapping of JavaScript resources, which is to assign the aliases to resources by using requirejs-config.js to create the mapping.
One example of requirejs-config.js file is shown as follows:
# magento2/vendor/magento/module-theme/view/base/requirejs-config.js /** * Copyright © 2013-2017 Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ var config = { "waitSeconds": 0, "map": { "*": { "ko": "knockoutjs/knockout", "knockout": "knockoutjs/knockout", "mageUtils": "mage/utils/main", "rjsResolver": "mage/requirejs/resolver" } }, "shim": { "jquery/jquery-migrate": ["jquery"], "jquery/jquery.hashchange": ["jquery", "jquery/jquery-migrate"], "jquery/jstree/jquery.hotkeys": ["jquery"], "jquery/hover-intent": ["jquery"], "mage/adminhtml/backup": ["prototype"], "mage/captcha": ["prototype"], "mage/common": ["jquery"], "mage/new-gallery": ["jquery"], "mage/webapi": ["jquery"], "jquery/ui": ["jquery"], "MutationObserver": ["es6-collections"], "tinymce": { "exports": "tinymce" }, "moment": { "exports": "moment" }, "matchMedia": { "exports": "mediaCheck" }, "jquery/jquery-storageapi": { "deps": ["jquery/jquery.cookie"] } }, "paths": { "jquery/validate": "jquery/jquery.validate", "jquery/hover-intent": "jquery/jquery.hoverIntent", "jquery/file-uploader": "jquery/fileUploader/jquery.fileupload-fp", "jquery/jquery.hashchange": "jquery/jquery.ba-hashchange.min", "prototype": "legacy-build.min", "jquery/jquery-storageapi": "jquery/jquery.storageapi.min", "text": "mage/requirejs/text", "domReady": "requirejs/domReady", "tinymce": "tiny_mce/tiny_mce_src" }, "deps": [ "jquery/jquery-migrate" ], "config": { "mixins": { "jquery/jstree/jquery.jstree": { "mage/backend/jstree-mixin": true } } } }; require(['jquery'], function ($) { $.noConflict(); });
To make oure configurations more precise and specific for different modules/thems, we can identify mapping in the requirejs-config.js file at several levels depending on our needs.
- Library configurations
- configurations at the module level
- configurations at the theme module level for the ancestor themes
- configurations at the theme module level for a current theme
- configurations at the theme level for the ancestor themes
- configurations at the theme level for the current theme
There are two ways we can initialize a JavaScript component in themplate files:
- Using the data-mage-init attribute
- Using the {script} tag
The data-mage-init attribute is parsed on a DOM ready event. Since it is initialized on a certain element, the script is called only for that particular element, and is not automatically initialized for other elements of the same type on the page. One example is as following:
The <em{script} tag initialization is done without relation to any specific element. The {script} tag has initialization would be something like the following:
Creating a custom JS component
Let’s go through a parctical example of creating a JS component within our Jeff_Office module (see Magento 2: Examples About Blocks and Templates).
First, we add our entry to app/code/Jeff/Office/view/frontend/rquirejs-config.js, as following:
var config = { map: { "*": { jeffhello: 'Jeff_Office/js/jeff-hello' } } };
The we add the actual JavaScript at app / code / Jeff / Office/ view /frontend /web /js /jeff-hello.js as follows:
define([ 'jquery', 'jquery/ui' ], function($) { "use strict"; $.widget('mage-jeffhello', { options:{ }, _create: function() { alert(this.options); } }); return $.mage.jeffhello; });
Finally, we call our JavaScript compoent within some PTHML template, app/code/Jeff /Office/ view/frontent/ templates/ office/hello.phtml:
Jeff Hello
Once we refresh the frontend, we should see the result of alter(this.options) in the browser showing var1Value and var2Value.
CSS
Magento 2 uses a PHP port of the official LESS processor to parse the .less file into .css files. Less is a CSS preprocessor that extends the CSS language by adding various features to it, like variables, mixins and functions. We can customize the storefront look and feel through one of the following approaches:
- Override the default LESS files — only if our theme inherits from the default or any other theme, in which case we can override the actual LESS files
- Create our own LESS files using the built-in LESS preprocessor
- Create our own CSS files, optionally having compiled them using a theird-party CSS preprocessor
Within the individual frontend them directory, we can find style sheets at the following locations:
- {vendorName}_{moduleName}/web/css/source/
- {vendorName}_{moduleName}/web/css/source/module/
- web/css/
- web/css/source
CSS files can be included in a page through templates and layout files. A recommended way is to include them through layout files. If we want our style sheets to be available through all pages on the frontend, we can use the default_head_blocks.xml file.
One example of default_head_blocks.xml as following: