Force Reload of Scripts and Stylesheets in your Plugin or Theme

If you’re developing a WordPress theme or plugin you may have had the problem that scripts or stylesheets are not reloaded from the source when you refresh the page because they are cached somewhere on the way from the server to the browser. There are various methods to suppress this behaviour like disabling the browser cache in the options or by using a web development add-on. Sometimes this simply does not work because it’s not always apparent where the content is cached since there are so many possibilities and you may have missed to disable all of them.

WordPress provides a simple method to ensure that all stylesheets and scripts are reloaded from the source when they have changed by providing a version parameter:

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

You can increase the $ver parameter every time you’ve changed the files:

wp_enqueue_script( 'my_script', 'my_script.js', '', '0.11' );
wp_enqueue_style( 'my_style', 'my_style.css', '', '0.11' );

The URL of the stylesheet/script will be changed to ‘.../my_script.js?ver=0.11‘ so that every caching system detects the changed file and reloads it from its source and the user always gets the recent version.

But to change the version number manually every time in the development stage would be a bit tedious and you’re a programmer, right? So let’s automate this:

wp_enqueue_script( 'my_script', 'my_script.js', '', time() );
wp_enqueue_style( 'my_style', 'my_style.css', '', time() );

The value of time() changes every second so the version ID of the file changes constantly and it’s reloaded from the source and not from some cache.

It’s a bit disadvantageous that you have to substitute the time based version parameter by a “real” version number every time you deploy your code since the actual user still should have the benefits of cached scripts and stylesheets. Let’s extend the idea:

define ('VERSION', '1.1');

function version_id() {
  if ( WP_DEBUG )
    return time();
  return VERSION;
}

wp_enqueue_script( 'my_script', 'my_script.js', '', version_id() );
wp_enqueue_style( 'my_style', 'my_style.css', '', version_id() );

This way you can make sure that in your development environment everything is reloaded from source all the time but a productive server takes advantage of caches.


Posted

in

by

Comments

12 responses to “Force Reload of Scripts and Stylesheets in your Plugin or Theme”

  1. Ozh Avatar

    neat idea, I’m adopting this 🙂

  2. Konstantin Avatar

    This is how I tackle the problem:

    wp_register_script( 'my_script', 'my_script.js', '', filemtime(PLUGIN_PATH . "my_script.js"), true);

    This way I get the time the file was last modified, don’t have to worry about bumping version numbers and the cache is always right.

  3. Latz Avatar

    @Konstantin: Good idea though I’m not sure if the value of “filemtime” isn’t cached by some system component, if not on your dev system then maybe on the user’s system. If the script/theme does not work correctly immediately after the update you will have a lot of mails complaining about it.
    Since the time/VERSION method will work in any case I’ll stick to that.

  4. Luke Avatar

    This is great! I changed it up a bit to use the theme version from the stylesheet. I can be forgetful and think I would probably not remember to update the version number in functions.php.

    function version_id() {
    if ( WP_DEBUG )
    return time();
    return theme_data( 'Version' );
    }

    function theme_data( $data ) {
    $theme_data = get_theme_data( STYLESHEETPATH . '/style.css' );
    return $theme_data[$data];
    }

    There are advantages both ways. Do you see any disadvantages with this method?

  5. Latz Avatar

    @Luke The problem with your attempt might be bad performance on busy sites. Every time you call get_theme_data() WordPress opens the theme file and reads the first 8Kb of data. Every single time it’s called, unless it’s cached … You see the problem?

    It my mind it’s not practicable to rely on data that COULD be cached somewhere.

  6. Luke Avatar

    Very true. I guess I’ll just have to remember to change it 🙂

  7. Edward Caissie Avatar

    Very nice idea; looks like another standard code snippet to be implemented.

  8. Erik Ford Avatar

    Up until recently, I was using my own “idiot proof” method, for our themes, with a function like so:

    function wap8_version_cache() {
    return '1.1.1';
    }

    And, then I would simply add the following when I register a script or stylesheet:

    wp_register_script( 'my-script', get_template_directory_uri() . '/js/my-js.js', array( 'query' ), wap8_version_cache(), true );

    This worked perfectly for me, but I would have to remember to update the version number in the function, which I would not at all times. I realized that I was in the habit of always updating the version number in the stylesheet and decided to grab that number, using the following.

    $shortname = 'themedirectoryname';
    $wap8_theme_data = get_theme_data( WP_CONTENT_DIR . '/themes/' . $shortname .'/style.css' );
    define( 'THEME_NAME', $wap8_theme_data['Name'] );
    define( 'THEME_VERSION', trim( $wap8_theme_data['Version'] ) );

    And changed my script registrations to the following:

    wp_register_script( 'my-script', get_template_directory_uri() . '/js/my-js.js', array( 'query' ), THEME_VERSION, true );

    But, if I am understanding Latz correctly, the second method is potentially problematic?

  9. Latz Avatar

    @Erik As I wrote in my answer to Luke there’s no problem with the programming logic but with the load on busy servers because you’re loading additional 8k from the theme file (get_theme_data()) every time a page or post is displayed. This should be no problem for most sites but it’s still an unnecessary overhead.

    Secondary you can’t be sure that the data from get_theme_data() isn’t cached somewhere.

  10. matt mcinvale Avatar

    I like @Konstantin’s solution.

  11. Rafael Ehlers Avatar

    I use a rand(), like this:

    <link rel="stylesheet" href="style.css?r=”>

  12. Rafael Ehlers Avatar

    again, because of the comment removed the opening php tag:

    <link rel="stylesheet" href="style.css?r=”>