How to optimize the loading of JavaScript scripts in Drupal 7

Drupal

This is the chapter number 11 of the series Practical Drupal Development. In this chapter I'm going to show you how to avoid render-blocking JavaScript in above-the-fold content with the help of the hook_js_alter() function and the Devel's module debugging function kpr().

The Goal

You owns a personal website powered by Drupal 7. After running the PageSpeed Insights (by Google), you are relatively satisfied with the speed result for mobile devices and you ask yourself how to prevent the following issue from happening:

Getting started

Drupal 7 is, without a doubt, a great framework for building amazing and robust websites, but, because of its modular nature, it’s quite easy to end up with a lot of references to CSS and JavaScript files in the head tag of your HTML document.

The more CSS and JavaScript references the worst will be the score you get. In addition, you’ll get the irritating message “Eliminate render-blocking JavaScript and CSS in above-the-fold content” because your browser is unable to load this part of the HTML document until the aforesaid CSS and JavaScript files are ready.

The fold is where the content of a page ends before visitors scroll down. This term comes from the fold in a newspaper.

Changing the location of JavaScript scripts

Even though changing the location of JavaScript scripts won't make your website faster, it’s the only way to fix the issue illustrated in the previous figure and gain in performance.

In Drupal 7, the hook_js_alter() function gives you a last chance to alter the JavaScript added to a page, so let’s use it to change the location of JavaScript scripts from the head section to the end of the body section of the HTML document.

1. Since you'll need the kpr() function for printing out the content of the javascript array, install now the Devel module if it’s not already.

2. Make sure that the JS files to which you want to change their scope and note that the keys to the javascript array depends on the type of Javascript you added to the page:

  • File and external Javascript is identified by the path to the file for its location.
  • Settings are available at $javascript[‘settings’].
  • Each time an inline Javascript is added to a page, it’s added by using a numeric value starting at 0.

3. Use the kpr() function along with the hook_js_alter() function in the template.php file to print out the content of the javascript array.

/**
 * Implements hook_js_alter().
 */
function themename_js_alter(&$javascript) {

  kpr($javascript);

}

This is how the javascript array looks after using the kpr() function:

3. Write down the keys to the Javascript scripts you want to take out of the head tag and complete the definition of the hook_js_alter() function.

The following piece of code is my definition of the hook_js_alter() function at the time of this writing:

/**
 * Implements hook_js_alter().
 */
function jhinfo_js_alter(&$javascript) {

  // Keys to the items in the array $javascript whose scope value will not be
  // changed to 'footer'. Add the scripts that you do not want to move
  // to the end of the body tag to this array. Use Devel module's
  // debugging function kpr(), Krumo Print Readable, to print out the
  // content of the array $javascript. Note that the default scope value
  // for all the Javascript scripts is 'header'.

  // Example:
  // $javascript_header = array (
  //   '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js',
  //   'misc/drupal.js',
  //   'misc/drupal.once.js' 
  // );
  $javascript_header = array();

  foreach ($javascript as $key => $value) {
    
    if (!in_array($key, $javascript_header)) {

      $javascript[$key]['scope'] = 'footer';
      
    }
 
  }

}

Once that the render-blocking JavaScript in above-the-fold content has been eliminated, the score is a little bit greater than it was at the beginning of the article.

79 out of 100... Well, it’s better than nothing!

Other issues to be considered to make the score even greater.

There are still three other issues that Google suggests you to fix: optimization of images, minification of JavaScript and CSS files, and elimination of render-blocking CSS in above-the-fold content. While the first two issues are easy to fix (there are plenty of sites providing these services for free on the Internet), the third one is not that simple.

Even though you could use the hook_css_alter() function to rearrange the CSS code, it would be still a pretty tedious task to deliver optimized CSS for fixing the issue about the render-blocking CSS in above-the-fold content because, as stated above, websites powered by Drupal normally end up with tons of CSS code.