Blog article

Code snippets, plus the latest news

lbfl ConsultancyCombine javascript files JavascriptHow to combine Javascript files in WordPress.

How to combine Javascript files in WordPress.

This is the process that increases the speed of your WordPress website by optimising the number of HTTP requests made by WordPress.

Plugins or manual optimisation?

There are many plugins which allow WordPress users to achieve this goal, however, these often fail to successfully merge javascript which can lead to problems when rendering the finished website. So rather than rely upon a plugin, we’re going to tackle this issue using a manual process.

Manual comination of Javascript files in WordPress.

Convention dictates that this is normally carried out by viewing webpage source (CTRL + F), then searching for javascript files using the ‘javascript‘ keyword. We then click the link and copy the javascript into a new javascript file.

This method is not recommended because of the number of drawbacks that you’re likely to encounter.

  • It’s hard to find the handle of the javscript file. Unlike the CSS file, you’ll struggle to find the handle, which is traditionally found on the CSS ID attribute. The handle is important, as we’ll need it to deregister scripts after we complete the javascript combination process.
  • If there’s an addition or subtraction of a javascript file, then you’ll need to recombine that file manually.
  • There’s no guarantee that javascript dependancy between files will work. This relates to the sequence in which javascript files are loaded.

How to combine javascript files automatically.

In order to combine files, we have to establish the names of all the javascript files and their associated handles, without the need to look at the webpage sourcecode, as we did using (CTRL + F) above.

Finding all the javascript files loaded on a webpage.

All the information relating to javascript files loaded in WordPress can be found in the WP_scripts object, which is stored in the $wp_scripts variable known as the hook. Hooks are objects like wp_head, wp_print, scripts, wp_footer, init, etc., which are often referred to in wp_enqueue_scripts.

Each hook yields different results, that is the number of javascript files are different, and this depends on how we load javascript files. There are two locations in which we can find all loaded javascript files, these are:

  • In the header (<head> tag). Javascript files loaded in the head can be established using the wp_head hook. This hook is run in WordPress before the <body> tag loads.
  • In the footer, before the closing </body> tag. Javascript files loaded in the foot can be established using the wp_footer hook. This hook is run in WordPress before the closing </body> tag.

You can establish both hooks by opening and modifying the functions.php file, which is in the theme folder that is being used. More often than not; it’s common practice to use a child theme, so for example we would modify and add the following code to wp-content/themes/child_theme_name/functions.php. functions.php normally exists within your child themes folder.

add_action( 'wp_head', 'show_head_scripts', 9999 );
add_action( 'wp_footer', 'show_footer_scripts', 9999 );
 
// Javascript handles before the header
function show_head_scripts(){
    global $wp_scripts;
    echo '<pre>'; print_r($wp_scripts -> done); echo '</pre>';
}
// Javasript handles in the footer
function show_footer_scripts(){
    global $wp_scripts;
    echo '<pre>'; print_r($wp_scripts -> done); echo '</pre>';
}

Open your webpage and you’ll see a complete list of handles output at the top and bottom of the page, like this:

How to obtain javascript header and footer file handles

Combining javascript files.

In order to combine all the javascript files, we must establish the javascript files which are automatically detected before our web page content is rendered. We can use the wp_enqueue_scripts hook for this purpose, although it does have a few drawbacks. However, it’s the only method available.

Combining javascript files into one.

  1. Javascript files handles MUST be sorted according to it’s first appearance (the ‘dependency‘). This is extremely important, so that the merged javascript file; which you’re going to create, can run without error. This is achieved by invoking the all_dep method on the WP_script object ( $wp_scripts -> all_deps ( $wp_scripts - > queue ) );
  2. Important – do not include dequeue or add the following file to your comined javascript file /wp-includes/js/jquery/jquery.js
  3. We now proceed to get the code from within each javascript file using file_get_contents and combine each into a single javascript file using file_put_contents
  4. We must then Deregister all script handles which have been combined. We do this after the combine scripts process has completed, simply because if we deregister a script first, then any dependencies will also be deregistered at the same time.
  5. Automatic execution of the tasks described above. To do the above, copy and paste the following into your functions.php file. Make sure that the process has worked. You’ll quickly see whether the combined process has worked, open your webpage, check visually and most importantly view the source. If the combined script has loaded and the other scripts have been dequeued, then this is what you’ll see.
add_action( 'wp_enqueue_scripts', 'combine_all_scripts', 9999 );
function combine_all_scripts() 
{
    global $wp_scripts;
    
    /*
        Reorder the handles based on dependency
    */
    $wp_scripts -> all_deps($wp_scripts -> queue);	
    
    // New file location eg: wp-content/themes/maintheme/js/combined-script.js
    $combined_file_location = get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'combined-script.js';
    
    $combined_script	= '';
    
    // Loop through javascript files and save to $merged_script variable
    foreach( $wp_scripts -> to_do as $handle) 
    {
        /*
            Clean up url, for example wp-content/themes/maintheme/main.js?v=1.2.4
            become wp-content/themes/maintheme/main.js
        */
        $src = strtok( $wp_scripts -> registered[ $handle ] -> src, '?' );
        
        /**
            Combine javascript files.
        */
        // If src is url http / https		
        if ( strpos ( $src, 'http' ) !== false )
        {
            // Get our site url, for example: http://lbfl.co.uk/
            $site_url = site_url();
        
            if ( strpos ( $src, $site_url ) !== false )
                $js_file_path = str_replace ( $site_url, '', $src );
            else
                $js_file_path = $src;
            
            /*
                To be able to use file_get_contents function we need to remove the trailing forward slash
            */
            $js_file_path = ltrim ($js_file_path, '/' );
        }
        else 
        {			
            $js_file_path = ltrim ( $src, '/' );
        }
        
        // Check to see if the file exists then combine
        if  ( file_exists ( $js_file_path ) ) 
        {
            // Check for wp_localize_script
            $localize = '';
            if ( @key_exists( 'data', $wp_scripts -> registered[ $handle ] -> extra)) {
                $localize = $obj -> extra['data'] . ';';
            }
            $combined_script .=  $localize . file_get_contents ( $js_file_path ) . ';';
        }
    }
    
    // write the combined script into current theme directory
    file_put_contents ( $combined_file_location , $combined_script );
    
    // Load the URL of combined file
    wp_enqueue_script( 'combined-script',  get_stylesheet_directory_uri() . '/combined-script.js' );
    
    // Deregister handles
    foreach( $wp_scripts->to_do as $handle ) 
    {
        wp_deregister_script($handle);
    }
}

Make sure that the process has worked.

You’ll quickly see whether the combined process has worked, open your webpage, check visually and most importantly view the source. If the combined script has loaded and the other scripts have been dequeued, then this is what you’ll see.

Combined javascript files

You’ll then need to make sure that there are no script errors. Open your browser (we’re using Firefox) open developer tools and select the console tab. If there are no errors you should see an empty Console listing. In our case errors are reported. an empty Console listing. In our case errors are reported.

Javascript console errors

If you do find errors, double check the message to ensure that the error is caused by the javascript in our script, or by something else. If there are no errors, the jobs finished! If there are errors, then carry on reading and carry out what we consider to be the best method – doing this manually.

Checking that other scripts have not been combined.

There are a several errors which are easy to deal with. Generally, these errors aren’t caused by the javascript code, but by resources which are loaded in the footer. Examples of an error that you’re likely to encounter Failed to load resource: further detail…

Check for other scripts which have not been combined.

If we check our webpage source again and search for script, you’ll find that the combined script exists, however, there are other scripts which have not combined.

Some scripts, as in our example are enqueued last of all, which simply means that the script above can’t catch them. This typically occurs when scripts are loaded in the footer.

So how do we solve situations like this? The only way to do so is to resort to using the manual method to combine scripts. This means that we have to examine all the scripts that are loaded in the footer, using our initial ‘Finding all the javascript files loaded on a webpage‘ shown near the top of this article.

For the purposes of this piece, we’re going to ignore the automated script and go back to basics. This method is long and complex and prone to error, but this is the way in which we’re going to proceed.

Manual approach to combining javascript in WordPress.

Fasten your seatbelts, it’s going to be a bumpy ride. So far in our example, we’ve established that there are reference errors: jQuery is not defined and CrayonSyntaxSettings are not defined. There are two causes of reference errors and these are:

    • Out of scope variables.
    • Undefined variables.

The actual cause of the error here is that jQuery isn’t loaded and CrayonSyntaxSettings aren’t in scope. Our approach must exclude all jQuery and CrayonSyntax scripts from the combined-script.js. In order to proceed we require the file handles which we output earlier, as we require these handles to dequeue scripts other than jquery-core, jquery-migrate, jquery and crayon_js, since these are the scripts which are causing reference errors. Here’s how we proceed in this manual approach:

    1. Combine all scripts other than jquery-core, jquery-migrate, jquery and crayon_js into a single script, combined-script.js.
    2. Save the comined-script.js to wp-content/themes/maintheme/js/combined-script.js or wherever your themes js files are located.
    3. Once we’ve completed the above and have uploaded the file to the appropriate file location on your server. Then we’re going to dequeue the file handles for all but the previously mentioned scripts, and then enqueue our newly created combined-scripts.js file.

It’s a lengthy process and be warned, if you make a mistake you could potentially break your WordPress theme, so TAKE YOUR TIME when ordering javascript in a combined script.

    1. For each handle in the list identify the javascript file and copy each javascript file. Using notepad++ or similar, create combined-scripts.js and then paste each javascript files content into this document, one below the other. This is the handle load order reported by the code at the top of the article. We’ve shown our handle listing below. Please note that we’re ignoring the first 4 listed items.
      [0] => jquery-core *
      [1] => jquery-migrate *
      [2] => jquery *
      [3] => crayon_js*
      [4] => prefixfree
      [5] => html5shiv
      [6] => respond

      The first file which we copy to combined-scripts.js has handle prefixfree, then html5shiv and so on…

    2. Repeat for each javascript file in your list of handles.
    3. When completed, save the file.
    4. Using filezilla or equivalent, upload combined-scripts.js to your chosen directory. In our case this is wp-content/themes/maintheme/js/combined-script.js.
    5. Next navigate to functions.php which will be either in your main theme; if you haven’t created a child theme, or in your child theme.
    6. Open functions.php and for each and every handle to be dequeued add the following code:
      [0] => jquery-core *
      /**
       * Dequeue scripts using their handles
       */
      function wp_dequeue_script() {
          wp_dequeue_script( 'handle-1' );
          wp_dequeue_script( 'handle-2' );
          // additional handles go here
      }
      add_action( 'wp_print_scripts', 'wp_dequeue_script' );
    7. Finally, in functions.php enqueue combined-script.js by adding this code:
      [0] => jquery-core *
      /**
       * Load the URL of our combined-script.js file.
       */
      function wp_load_combined_script() {
                             //script handle                                   script location
          wp_enqueue_script( 'combined-script', get_template_directory_uri() . '/js/combined-script.js' );
      }
      add_action( 'wp_enqueue_scripts', 'wp_load_combined_script' );

Test and repeat, as per the automatic process. This takes time, although it’s worth it if Page Speed matters to you!

Conclusion.

It’s a lengthy article, but it well worth understanding how WordPress functionality and performance can be improved. In our next article, we’ll look at combining CSS files, in order to reduce server load in order to improve your website performance.