Magento – Magento – Defer Parsing of Combined Javascript File

javascript

How would I defer parsing of Javascript in magento on a combined JS file?

In System –> Configuration, I have it set so that all JS files are combined into one file.

I found a solution on another thread, which is to use the "defer" keyword on the script tag:

<script type="text/javascript" defer="defer"> 

I am unsure how to add that to the script tag since the combined JS file is created and added in by Magento.

My question is, how do I add the "defer" keyword into the script tag if all of my JS is combined in a single file?

Or, is there a better, or more easier way to defer parsing of Javascript using another method?

Please don't mark as duplicate, I've checked all of the other threads similar to my question, but the answers don't contain instructions on how to implement, or they simply aren't good answers.

Thank you.

Best Answer

As you correctly pointed out the JS lines are generated by Magento. Specifically these are built in app/code/core/Mage/Page/Block/Html/Head.php which is the block behind the head.phtml template.

Inside this block we have the method getCssJsHtml which generates an sprintf template for each CSS or JS reference.

For the JS scripts the template has the following format: <script type="text/javascript" src="%s"%s></script> As we can see it accepts 2 variables. First is the URL and the other is a set of parameters; exactly what we need.

To add parameters to a JS link, is very easy. Simply add <params>defer="defer"</params> in the XML tag which defines the file. For example:

<action method="addJs"><script>mage/cookies.js</script></action>

becomes

<action method="addJs"><script>mage/cookies.js</script><params>defer="defer"</params></action>

Your question though makes a reference to merged JS files. Well, Magento also takes care of that, and merges the files based on their parameters. Meaning if you include some files with the defer parameter, and the others without, Magento will create 2 merge files (one for defer, and one for the others). This is done in the Head.php block file, line 260

foreach ($items as $params => $rows) {
    // attempt to merge
    $mergedUrl = false;
    if ($mergeCallback) {
        $mergedUrl = call_user_func($mergeCallback, $rows);
    }
    // render elements
    $params = trim($params);
    $params = $params ? ' ' . $params : '';
    if ($mergedUrl) {
        $html .= sprintf($format, $mergedUrl, $params);
    } else {
        foreach ($rows as $src) {
            $html .= sprintf($format, $src, $params);
        }
    }
}

As you can see, it groups the files based on their custom parameters (attributes), and merges them.

But be careful when defering JS files. Some of them include functions, plugins, objects that are used inside the templates before the page finishes loading. And as you know defering a JS file means it can load after the HTML has finished loading, so you might end up with Reference error: * is undefined errors