Magento 2: Four Ways to Add JavaScript

Magento 2: Four Ways to Add JavaScript
May 20, 2020
Magento 2: Four Ways to Add JavaScript

In this article, we are going to learn four methods of adding JavaScript to Magento 2. To get a clear understanding of this process, we will also  talk about advantages and disadvantages of each way.

Let's go!

#1. Using  <script type=”text/javascript></script>

This is considered to be the easiest, however, it's quite unreliable way. Its one and only advantage is simplicity! According this method can be justified if you want to connect third-party libraries. In other cases, this approach has several significant drawbacks.

Firstly, the code will be difficult to use again and it can block the page loading (of course, it depends on what the script contains).

Secondly, it is obvious that as the complexity of the project increases, it becomes very difficult to control such a code. When discussing this method we should also mention CSP (Content-Security-Policy). The third issue is that the code connected in this way is highly vulnerable to CSS attacks (Cross-site scripting). If you still want to use this method, then you should add the following attributes when connecting: deferred="true", async="true".

#2. In Magento style

Now, let’s look through the ways to connect JS scripts in Magento style. First of all, it’s worth mentioning that Magento 2 uses RequireJS scripts to connect JS. This approach allows using JS modularly as well as background and asynchronous loading. To learn more aboutRequireJS, follow the link. So, the first way is to use the special data-mage-init attribute . The attribute must contain the path to the JS module as a value, the element which we want to apply our JS code to and configuration parameters. For example, imagine that we have a RequireJS module that calls a popup window.

Let’s create a JS file in the following directory: app/code/Magezend/AddJavascript/view/frontend/web/example.js

Next, we will write the following code inside the file:

define([], function(){ 
 alert("A Magezend Example module"); 
}); 

Now, let’s say there is a certain template in which we want to connect our JS module. For the beginners, we can connect it the following way:

<div class="example-element" data-mage-init="{"Magezend_AddJavascript/example": {}}">A Magezend Example div</div>

When loading a page, the browser will simply show a pop-up window with the specified text. Nothing special, but what if we pass some configuration values to data-mage-init? For example, let’s add this:

<div class="example-element" data-mage-init="{"Magezend_AddJavascript/example": {"config": "value"}}">A Magezend Example module</div>

And then we change the JS module in the following way:

define([], function(config){
 alert("A Magezend Example module");
 console.log(config); 
});

After reloading the page, you will get the same pop-up window, but in the console, you will see the value of the config parameter equals the value.

Following the same steps, we can pass any parameters inside our JS module. In addition to that, we can pass a DOM element as a parameter, on which we call our script. In order to do it, we rewrite our module in the following way:

define([], function(config, element){ 
 alert("A Magezend Example module"); 
 console.log(config); >
 console.log(element); 
}); 

Reload the page again anh check the console of browser, the output of the element will be added there. In our case, this will be

<div class="example-element"></div>

We can also come across a situation, when we pass a group of arguments to our block using thetag in the layout. If we want to get these arguments as parameters for our JS module, then we need to pass them in the following way:

<div class="example-element" data-mage-init="{"Magezend_AddJavascript/example": < ? = /* @escapeNotVerified */ $block->getJsLayout() ? > ">A Magezend example div</div>

We get JSON as an input parameter, which we can further use at our discretion. Often we have to pass more than one argument to our module. The syntax that was described above can be difficult to read, so type=”text/x-magento-init” can be used as an alternative. It looks like this:

<script type="text/x-magento-init"> {
 ".example-element": {
 "Magezend_AddJavascript/example":{
 "config":"value",
 "config2":"value2",
 "config3": "optionConfig": < ?php /* @noEscape */ echo $block->getJsonConfig()?>

 }        
 }
 }
<script>

As you can see, this code is much easier to read.

#3. The imperative approach

It is also worth to mention here the so-called imperative approach in connecting JS modules. You can often find it in the Magento 2 code. However, it is recommended in the Magento 2 official documentation not to use it. Here is what the connection looks like:

<script type="text/javascript">
require( [
 'jquery'
 ],
 function($) {
 alert('Magezend Example');
 });
 }
);
</script>

#4. Via require-config.js file

Finally, let’s consider the situation when we need to connect the script not at the same page and in a specific element, but on multiple pages at once. In this case, you can use the require-config.js file, which needs to be created in the module folder in the view/base/require-config.js sub-directory. The content should look like this:

var config = { 
deps: [ 'Magezend_AddJavascript/js/example',
 'AnotherMagezend_AddJavascript/js/example', 
] 
};

Then, the scripts we have connected will work on all the pages of the module. Usually, some third-party libraries are connected in this way. You can also set the map property and define the prefixes for various modules. In the future, we can use these prefixes to connect the required JS modules in other modules. For example:

var config = { 
 map: { " * " : 
 { 
 "example_alias": "example.js" 
 } 
 } 
} 

Now, we can use the created alias to connect the corresponding JS module:

define([ "jquery", "example_alias" ], 
function($, config){ 
/* code goes here */ 
}); 

If you need to determine the loading order of JS files, you can use the shim option. Now let’s consider injecting dynamic content and executing JavaScript in data-mage-init and x-magento-init. In order to do it, you can just insert the content in DOM and after that trigger the event ‘contentUpdated’. For example, it can look like this:

 $.ajax({  
url: 'https://www.you-url.com',  
method: 'GET'  
success: function (response) {  
$('#element').html(data) .trigger('contentUpdated')  
} });  

#5. Wrapping it up

 It’s a common knowledge that adding JS increases page loading time, which can negatively affect your webstore. What can you do in this case? We would strongly recommend you to try Defer JS for Magento 2 module which moves JavaScript to the bottom of the page and speeds up loading. With this module you will be able to install JavaScript keeping your webstore fast.

We hope that everything was clear but if you have any questions, leave them below.

Thanks for reading!

Download Free Magento Extension at here (click here)