Site Speed WTF?!

Weekly Email

Please wait…


You have subscribed! A verification email will be sent to you.


SpeedGuard tracks Core Web Vitals from your WordPress. Check it out.

Force CSS and JS refresh in WordPress during development

So, you are developing theme or customizing plugin and have made some changes to your custom stylesheet.

You refresh your page and… nothing happens. You clear browser cache but stylesheet still not updating. You go into incognito mode but it changes nothing. You check caching plugin’s settings but … WordPress stylesheet changes not showing up no matter what!

Why style.css or any other not updating in WordPress?

It happens because of how caching works (browser, page caching, server side, CDN etc).

Check out in the page source code your file URL:

Usually:

  • /style.css — will be cached
  • /style.css?ver=5.7 — will be cached
  • /style.css?ver=something else — will be cached too

So, if you make changes to a file but its URL and query arguments didn’t change accordingly most likely it will be cached. And changes you made won’t be applied.

There is a really easy way to fix this not updating stylesheet (or JavaScript file) issue.

All you have to do — is just set ?ver correctly so it is updated once you update the file itself.

File versioning and caching

In WordPress styles and scripts are included using wp_enqueue_style and wp_enqueue_script

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

See this fourth $ver parameter? This is the answer to that not-updating-stylesheet issue. WordPress gives us a simple method to specify stylesheet version number for cache busting purposes.

$ver (string|bool|null) (Optional)
String specifying stylesheet version number, if it has one, which is added to the URL as a query string for cache busting purposes. If version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added.
Default value: false

If you enqueue a script or a style without specifying it’s version

Like this:

wp_enqueue_style('my_custom_style', get_stylesheet_directory_uri() . '/sz_style.css');

It means the default value will be set for $ver, which is ‘false’.  Meaning that the number of currently installed WordPress core version will be assigned. Say, 5.7:

Force CSS and JS refresh in WordPress during development

If you set $ver parameter to NULL

Like this

 wp_enqueue_style('my_custom_style', get_stylesheet_directory_uri() . '/sz_style.css', array(), NULL);

No version will be added:

But it still will be cached and not updating when you make changes.

If you set $ver according to your theme/plugin version or manually

Like this

wp_enqueue_style('my_custom_style', get_stylesheet_directory_uri() . '/sz_style.css', array(), '1.1'); 

And you get:

You’ll get the same result: once you update version number, a new file version will be applied (you’ll see the changes) and it will get cached too. So next time you update a file you face the very same problem — style.css is not updating.

A proper solution: Force CSS reload in WordPress every time when file is updated

In $ver — check if actual file has changed, and if so — update it’s version number.

wp_enqueue_style(
    'my_custom_style', 
    get_stylesheet_directory_uri() . '/sz_style.css', 
    array(), 
    filemtime( get_stylesheet_directory_uri() . '/sz_style.css')
);

This part:

filemtime( get_stylesheet_directory_uri() . '/sz_style.css')

will check when the script or stylesheet file you are adding was modified and fetch that time in Unix Timestamp format.

In this example, 1617209817 = Wed Mar 31 2021 16:56:57 GMT+0000

So the version of the CSS or JavaScript file you enque will be equil to thetime it was modified.

And that style or script you enqueue will be reloaded only in case its file has been changed. Exactly what we need!

9 responses to “Force CSS and JS refresh in WordPress during development”

  1. Bruno Avatar
    Bruno

    Great article!
    I am having the following error : filemtime(): stat failed
    Any ideas?

    1. jerry Avatar

      filemtime() ‘stat failed’ is caused by a bad parameter string

      i find that this works well:
      $timestamp = filemtime( plugin_dir_path( __FILE__ ) . ‘my-file.js’ );

  2. Bruno Avatar
    Bruno

    Great article!
    I am having the following error : filemtime(): stat failed
    Any ideas?

    1. jerry Avatar

      filemtime() ‘stat failed’ is caused by a bad parameter string

      i find that this works well:
      $timestamp = filemtime( plugin_dir_path( __FILE__ ) . ‘my-file.js’ );

      1. Adil Avatar
        Adil

        Hello Jerry, did it work well for you?

  3. Jerry Avatar

    Hi Sabrina,
    Thanks for pointing me in the right direction. I’ve been tearing my hair over why Chrome wasn’t getting the latest js file.
    Timestamp is a great solution however when implementing your code, it still wasn’t working.
    On investigating I discover that a short parameter for $ver .. something like ‘1.323’ appears in the url for the js file like ‘?ver=1.323’. When you manually change the $ver.. say ‘1.324’, the url changes and Chrome loads the new js file properly.
    However, using the timestamp value always results in the same value no matter what the timestamp is . In my case ‘?ver=faa9b2eb156861f5075e6d027eb1e916’.

    I assume something in wp_enqueue_script is truncating the $ver parameter.

    my solution:
    $timestamp = filemtime( plugin_dir_path( __FILE__ ) . ‘my-file.js’ );
    $ver = date( ‘His’, $timestamp );
    Resolves to something like ‘104323’ ie. 10:43 and 23 seconds
    I reckon that should be unique enough!

    Chrome now reloads everytime I change my js file.

  4. Jerry Avatar

    Hi Sabrina,
    Thanks for pointing me in the right direction. I’ve been tearing my hair over why Chrome wasn’t getting the latest js file.
    Timestamp is a great solution however when implementing your code, it still wasn’t working.
    On investigating I discover that a short parameter for $ver .. something like ‘1.323’ appears in the url for the js file like ‘?ver=1.323’. When you manually change the $ver.. say ‘1.324’, the url changes and Chrome loads the new js file properly.
    However, using the timestamp value always results in the same value no matter what the timestamp is . In my case ‘?ver=faa9b2eb156861f5075e6d027eb1e916’.

    I assume something in wp_enqueue_script is truncating the $ver parameter.

    my solution:
    $timestamp = filemtime( plugin_dir_path( __FILE__ ) . ‘my-file.js’ );
    $ver = date( ‘His’, $timestamp );
    Resolves to something like ‘104323’ ie. 10:43 and 23 seconds
    I reckon that should be unique enough!

    Chrome now reloads everytime I change my js file.

  5. John T. Avatar

    This is so close, but not quite right:

    filemtime( get_stylesheet_directory_uri() . ‘/sz_style.css’)

    It’s the inclusion of “_uri” that is incorrect. It should be this:

    filemtime( get_stylesheet_directory() . ‘/your_style_sheet.css’)

  6. John T. Avatar

    This is so close, but not quite right:

    filemtime( get_stylesheet_directory_uri() . ‘/sz_style.css’)

    It’s the inclusion of “_uri” that is incorrect. It should be this:

    filemtime( get_stylesheet_directory() . ‘/your_style_sheet.css’)

Leave a Reply

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