Start Your Project

I need help with...

Debugging Javascript and Require JS – Part 2

In the last section, we talked about the Network tab of the browser. In this post, we are going to dig into how to control the way files are output to the browser from Magento. This is going place you in the driver seat of this massive application. Get your crash helmet!!!

The RequireJS Configuration file

When we looked at the page source in the first post of this series, we saw one of the files being loaded into the head of our site is the requirejs-config.js file. This file compiles into the pub directory and is the combined output of all the requirejs-config.js files that exist in the modules and themes of the site. Opening up this file (you can do this in your code editor here: pub/static/frontend/{{vendor_namespace}}/{{theme}}/en_US/requirejs-config.js or in the browser itself in the page source view of the site) you will see chunks of code.

This picture is just an arbitrary chunk. Each section starts with an anonymous function that wraps a config object. Inside that object is our configurations (map is just one of the configurations we can do). We then see require.config(config); followed by () which will execute this chunk of code.

Inside the map you can think of this as a key/value pair, where the name is the first element and the path to the file is the second. Actually, you don’t have to think of it that way, that is exactly what this is. We have already seen this in a past post, in there we have this code:

...
map: {
    '*': {
        slick: 'Magento_Theme/js/vendor/slick.min'
    }
}
...

Here we are pointing to a file location (given Magento’s shorthand path system that omits the web directory and the .js file extension) and then give it a name: slick. Later in that post we “grabbed” this file to use it in our define statement. This configuration file is what makes the connection between these elements. In plain language: we register the file under the label slick and then use that label to call the script into our custom file.

When the page is loaded, all the Javascript that is rendered in the HTML document will have been defined by this configuration file. All the interdependent assets needed will be loaded by RequireJS in the background. We have already talked about debugging this load order in the network tab of the browser. This file is the starting point of how that order is defined.

That leads up to one of the superpowers of RequireJS. It stores its configuration file in a way that makes all modules defined accessible from anywhere else in the application. To find the definition of “jquery” (using a search like find src/vendor/magento -name 'requirejs-config.js' | xargs grep -r 'jquery') you will find that this is loaded in vendor/magento/module-theme/view/base/requirejs-config.js. But once loaded, any other module in the system can now use that instance of jQuery.

This frees us as end users of the system to just grab the things we need to use and not worry about where they are or how to get them. You need the underscore library. Place 'underscore' in your file. Need the validation library? 'mage/validation' gets the job done.

It also means that we can load in our own libraries and dependencies into the framework without the worry of namespace conflicts and global variables causing havoc on our pages.

To continue our tour, another part of the file is this:

'shim': {
    'jquery/jquery-migrate': ['jquery'],
...
},

Here we see a RequireJS shim. In this, we can set dependencies. In this case jquery/jquery-migrate depends on ['jquery']. This explicitly says “hey, no matter what, load my file after this other file, I have to have it first”. The dependency is an array and can contain multiple dependencies if needed: ['jquery, 'underscore', 'tacos'].

The next thing I want to cover in this file is mixins. There will be a lot of use of this in future posts, but I need to do a quick introduction here.

config: {
    mixins: {
        'Magento_Theme/js/view/breadcrumbs': {
            'Magento_Theme/js/view/add-home-breadcrumb': true
        }
    }
}

Mixins are an override system in place that will “extend” the existing Javascript module with changes to the methods inside it, add new methods or take the output of those methods for further processing. I cannot overstate the value of this functionality. I use this almost every day, and it is a critical tool in the front end developers box.

For a deep dive into mixins, Alan Storm has written an amazing article on this topic.

Wrapping up

So we have solved a big problem with the use of RequireJS. But is all that worth it? Well in the case of Magento 2, there really is no other choice. This new iteration of the platform is Javascript powered in a way Magento 1 never was. To accomplish a truly modular system the idea of just “dealing with” Javascript conflicts is too much to ask. These kind of errors aren’t even an option for a platform like Magento. So good or bad, right or wrong, a system like RequireJS had to be used.

Up Next!

We have done enough theory, in the next blog post we are going to start to use these tools to get work done.

Author:

Mike Stacey