Busting client-side js/css in WordPress

When was the last time you made a change to a site and the Project Manager or client says something to the affect of “I don’t see the change.” Then you have to tell show them how to clear their cache so the css of js change you made gets updated, not to mention that every other returning user to that site will have the same issue.

I had always meant to fix this issue, but I knew I’d have to add a random query string to each css or js file, and let’s be honest, I’m not going to do that every time.

After poking around on the WordPress Codex, there is a way to completely automate this process so you never have to think about it again.

Enqueue scripts and styles through WordPress

This is something you should be doing anyway, so WordPress knows that these files exist. The Codex have some pretty good docs on css and js enqueuing, but here’s what the syntax looks like that you put in your functions.php:

wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );
wp_enqueue_style( $handle, $src, $deps, $ver, $media );

As you can see, the css and js enqueue functions are just a little different. The important parameter in here is $ver which stands for “version”.

So what WordPress wants you to do is add a string to that parameter (a date would be appropriate) and when you commit a change to that js/css file, you go in and change that string. When I brought this up to my coworker Matt Meyer, he let me know that there is a way in php to the get last modified date of a file. Perfect! Now we can completely automate this. Here is was your enqueuing code should now look like:

wp_enqueue_style( 'style', get_template_directory_uri() . '/style.css', array( 'fonts' ), filemtime( get_stylesheet_directory() . '/style.css' ) );
wp_enqueue_script( 'main_js', get_template_directory_uri() . '/js/main.min.js', array('jquery'), filemtime( get_stylesheet_directory() . '/js/main.min.js' ), true );

Notice that I’m using the get_stylesheet_uri() function when setting $handle param, but in the $ver param, I’m using get_stylesheet_directory(). The difference is that get_stylesheet_directory() function outputs a browser-friendly path (like https://ryantvenge.com/wp-content/themes/tvengedesign_30/), and get_stylesheet_directory() outputs the full server path (like /home/serveruser/public_html/wp-content/themes/tvengedesign_30/) so php can find the file and read the “last modified” date.

This was the tipping point for me to enqueue everything. I knew it was something I should be doing, but was just too lazy. Now that clients’ cache is automatically busted, I’m sold.

Edit: If you aren’t aware how enqueuing scripts work in the functions.php file, you want to put your enqueues in this function and add the action:

function my_scripts_method() {
    // use wp_enqueue_script() and wp_enqueue_style() here
add_action( 'wp_enqueue_scripts', 'my_scripts_method' );

Thanks to Gordon for pointing this out in the comments. 🙂

Edit 2: Thanks Morgan for pointing out that like a noob, I mixed up get_stylesheet_directory() and get_stylesheet_uri(). I did fix this throughout the article.

3 thoughts on “Busting client-side js/css in WordPress

  1. Gordon Williamson says:

    Also, you should put these enqueue calls inside a function called by the ‘wp_enqueue_scripts’ hook.

  2. This is great info, but I believe you have two functions swapped:
    get_stylesheet_directory() returns the path to the current theme folder, and get_stylesheet_directory_uri() returns the URL to the theme folder.
    You want to use the 2nd one to pass as $src (the URL to the file) and the 1st to check for filemtime().

  3. Thanks for pointing that out Morgan! Noob mistake. haha.

Leave a Reply

Your email address will not be published. Required fields are marked *