Looking around for when <scripts>
are focused on during the WP process, I found the following action hooks that are registered.
// In default-filters.php of WP core
add_action( 'wp_head', 'wp_enqueue_scripts', 1 );
...
add_action( 'wp_head', 'wp_print_styles', 8 );
add_action( 'wp_head', 'wp_print_head_scripts', 9 );
...
add_action( 'wp_footer', 'wp_print_footer_scripts', 20 );
...
add_action( 'wp_print_footer_scripts', '_wp_footer_scripts' );
First thing to notice is that there is a function called wp_enqueue_scripts() that is called almost first thing (priority 1) during the wp_head
action hook. Let’s see what that function does:
// In script-loader.php of WP core
function wp_enqueue_scripts() {
/**
* Fires when scripts and styles are enqueued.
*
* @since 2.8.0
*/
do_action( 'wp_enqueue_scripts' );
}
Something interesting WP devs do, create a wrapper for a do_action
. I guess that gives some flexibility and allows one to create a ‘sub-action’ (I don’t know if that would really be what its called). The end result being that any actions added to wp_enqueue_scripts hook will be called during priority 1 of the wp_head action.
The actions added to the wp_enqueue_scripts hook are functions we create that run the wp_register_script()
, wp_enqueue_script()
, wp_register_style()
, and wp_enqueue_style()
calls containing the scripts and styles we want to have on the page. These are WordPress core functions that will add your scripts and styles to a collection. It does not add them to the page.
The end result being that any actions added to `wp_enqueue_scripts` hook will be called during priority 1 of the wp_head action.
It is at the wp_head action at priority 8 and 9 when the styles and scripts destined to the <head>
section are output to the page’s markup.
Why do we have both ‘register’ and ‘enqueue’?
They both can take the same arguments and they both put your script in a collection of scripts that could be outputted/printed to the HTML page. In fact, you could just use the ‘enqueue’ functions and never use the ‘register’ function. The ‘enqueue’ function technically ‘registers’ the script. But there is good reason to sometimes only use the ‘register’ function. Let’s see when that is.
The order the scripts are placed on the page is very important as some scripts depend that another script is already on the page. For instance, jQuery is a common dependency for scripts to run. The collection of scripts we register or enqueue is ordered based on any dependencies you might have put in one of the arguments. While scripts can be either in the <head>
or <footer>
sections of a page, WordPress needs all the scripts registered or enqueued before the <head>
finishes outputting so it can determine the order of the collection. Actually, from the above code, we see that WordPress needs all scripts registered and/or enqueued before priority 8 and 9 of the wp_head action.
Ok, so…
When do we use wp_register_script() instead of wp_enqueue_script()?
In the wp_enqueue_scripts action, we want to only register a script when:
- The script can be printed in the <footer> section, AND
- we will determine later if this script needs to be on this page.
If we just register a script and never enqueue it, it will not be put on the page. On the other hand, if we register and later in the page creation process but before the wp_footer action, we enqueue that already registered script, it will be put on the page.
WordPress needs all scripts registered and/or enqueued before priority 8 and 9 of the wp_head action.
An example of when we would do this would be for JavaScript we wanted to add if the page content had a shortcode that needed it. We won’t know if a shortcode is in the content of the page/post until long past the wp_head action has run.
//if part of theme, in the theme's functions.php
add_shortcode( 'jht_ideas', 'jht_ideas_app' );
add_action( 'wp_enqueue_scripts', 'jht_enqueue_scripts' );
function jht_enqueue_scripts() {
wp_register_script('jhtscripts', get_bloginfo( 'stylesheet_directory' ) . '/js/dist/app.js', array('jquery'),'1.0.0',true); // 'true' here says put script in footer if possible.
// 'array('jquery')' says this script depends on jquery.
}
function jht_ideas_app($atts, $content=null) {
// do something here...
wp_enqueue_script('jhtscripts'); // tell WP we want the jhtscripts on the page.
$output = '';
return $output;
}
This code will allow us to only put our JavaScript on the page if the page/post has a shortcode in it.
When is the last point we can enqueue a registered script
Based on the core WP code, it is at priority 20 of the wp_footer action when the last of the scripts are placed on the page. The last point to enqueue any registered scripts and get them on the page would be at the wp_footer action. If you don’t put a priority argument when you add_action(), it will be placed in priority 10 before the _wp_footer_scripts is run at priority 20.
Why do we do all this?
Why not just enqueue everything and be done with it. The main reason is for performance and optimization of your web page. One gripe I have with some plugins is that they load all their css and javascript on every page of your site when it may not even need it for that page. It is always best to only load what is needed.
This article was inspired by the following blog post: https://mikejolley.com/2013/12/02/sensible-script-enqueuing-shortcodes/