Enqueuing Scripts With Dynamic Hashes in WordPress

While WordPress’ system of loading scripts and styles is a vast improvement over hard coding these files in the head and footer of a site, they struggle with modern web build systems like Webpack. These tools allow us to have development environments in our IDE’s that make coding so much more efficient and less error prone. As an added bonus, when we’re ready to take our work into production, they handle optimizing all of our HTML, JS and CSS so everything loads efficiently.

Each file that is created by these tools has a “hash” in it. That’s basically a string of letters and numbers that gets changed each time the app is built. That let’s our visitor’s browsers know when the file they have cached has been replaced so they can load a new one. WordPress’ native enqueuing system has a similar feature by adding variables to the end of the files to let browsers know there has been a change, but those variables are not part of the names of the files themselves unlike these hashes.

Google’s speed tools does not like these variables and if you’ve ever tested a standard WordPress theme with tools.pingdom.com or other tool, you’ve likely seen some points deducted for these variables.

But our shiny new app is built with webpack and we can skip these variables and still let the browser know the file had been updated because of these hashes. The trouble is each time we make a build we have to change the name of the each file where they are enqueued. Like all developers I hate repetitive manual tasks so I looked for an option and found one on CSS Tricks.

So the following snippet does a few things for us. It lets us define a folder in our theme that will house these javascript files that are being built by Webpack. Inside that folder it will look for the files by their base name and then enqueue them, with the correct hashes. Here’s what the code for that looks like:


function wpwa_legendary_enqueue_hashed_js() {
$dirJS = new DirectoryIterator(get_stylesheet_directory() . '/static/js');
foreach ($dirJS as $file) {
if (pathinfo($file, PATHINFO_EXTENSION) === 'js') {
$fullName = basename($file);
$name = substr(basename($fullName), 0, strpos(basename($fullName), '.'));
switch($name) {
case 'app':
$deps = array('vendor');
break;
case 'vendor':
$deps = array('manifest');
break;
default:
$deps = null;
break;
}
wp_enqueue_script( $name, get_template_directory_uri() . '/static/js/' . $fullName, $deps, null, true );
}
}
}
add_action( 'wp_enqueue_scripts', 'wpwa_legendary_enqueue_hashed_js', 0 );

view raw

gistfile1.txt

hosted with ❤ by GitHub

In my theme I have a folder called static with a js folder in it where these files live. The order that these files are loaded matters greatly so I set a few “cases” so I can set a dependency. The file with “app” in its name needs the one called “vendor” to be loaded first so it’s listed as a dependency. “Vendor” also needs a file called “manifest” to be loaded first so it gets a dependency.

So that causes our enqueue order to be manifest, vendor and app because manifest is the only file that doesn’t specify a dependency. If any other files are in this folder they will be enqueued if they end with a js file extension. This folder also contains files that are .map so they won’t be enqueued. These source maps are for debugging our javascript which is something we do before rolling it into our WordPress theme anyway so they aren’t needed here.

We can also do the same thing for the CSS so we’re not running into the same issue there.

Hopefully this technique will help you as you work with WordPress and single page apps.


Leave a Reply

%d bloggers like this: