Home / Javascript and CSS file timestamps with PHP

Javascript and CSS file timestamps with PHP

Many websites I have worked on have frequently modified CSS style sheets and Javascript library files. In order to prevent Javascript errors or layout and style issues caused by web browsers caching these files, I used to rename the file for each revision, and then modify the name of the CSS or JS file in my PHP header include files.

Update March 20th 2009: Please note that I have posted an updated version of this which doesn’t use query strings. Refer to my newer post titled "Force reload of updated CSS and Javascript files with unique filenames" for details. Update ends.

When there are frequent updates to these scripts and style sheets it is important that the browser gets the correct version each time. This is especially important during development when you want the client to always see the up to date, non-cached version without having to instruct them to reload or clear the cache each time. However, it can become a little cumbersome renaming files all the time.

It was suggested to me that instead of renaming the file each time, we simply added a query string to the end of the stylesheet filename, or the javascript file name. This could simply be a number to indicate the version or the date or so on. Then we would just need to update the include file which had the <head> part of the HTML template.

Examples of this are as follows:

Using version numbers:
<link rel='stylesheet' type='text/css' href='/css/common.css?1'    />
<link rel='stylesheet' type='text/css' href='/css/common.css?2'    />
<link rel='stylesheet' type='text/css' href='/css/common.css?3'    />

Using the date:
<link rel='stylesheet' type='text/css' href='/css/common.css?20070910'    />
<link rel='stylesheet' type='text/css' href='/css/common.css?20070911a'    />
<link rel='stylesheet' type='text/css' href='/css/common.css?20070911b'    />

Javascript example:
<script type='text/javascript' language='javascript' src='/js/common.js?20070911'>
</script>

This is still a little cumbersome, because it means having to modify and upload the template files as well as the CSS and Javascript files each time a change is made.

Some time later, I decided it would be much easier to get the PHP to look at the timestamp the file was last modified and append that to the query string instead. That way every time the file was updated it would be automatically updated in the template and the most current version of the file always requested from the web server. Then I would only need to upload the changed Javascript or style sheet and not bother about modifying the template files.

The examples below assume the PHP code is in a common include file, in the includes directory of the of the following directory structure:

htdocs
htdocs/css
htdocs/js
includes

An example of doing this for a CSS style sheet in PHP is as follows:

$filemtime = filemtime(dirname(__FILE__) . '/../htdocs/css/style.css');
echo "<link rel='stylesheet' type='text/css' href='/css/style.css?$filemtime'    />n";

result:

<link rel='stylesheet' type='text/css' href='/css/style.css?1189482039'    />

An example of doing this for a Javascript file in PHP is as follows:

$filemtime = filemtime(dirname(__FILE__) . '/../htdocs/js/common.js');
echo "<script type='text/javascript' language='javascript' src='/js/common.js?$filemtime'>n";
echo "</script>n";

result:

<script type='text/javascript' language='javascript' src='/js/common.js?1189482039'>

This can also be done with arrays of filenames, which makes it easy to include multiple javascript files or style sheets.

$css = array(
	'common.css',
	'menus.css'
);

foreach($css as $filename) {
	$filemtime = filemtime(dirname(__FILE__) . '/../htdocs/css/' . $filename);
	echo "<link rel='stylesheet' type='text/css' href='/css/$filename?$filemtime'    />n";
}

result:

<link rel='stylesheet' type='text/css' href='/css/common.css?1189482083'    />
<link rel='stylesheet' type='text/css' href='/css/menus.css?1189482083'    />

Javascript example

$js = array(
	'common.js',
	'menus.js'
);

foreach($js as $filename) {
	$filemtime = filemtime(dirname(__FILE__) . '/../htdocs/js/' . $filename);
	echo "<script type='text/javascript' language='javascript' src='/js/$filename?$filemtime'>n";
	echo "</script>n";
}

result:

<script type='text/javascript' language='javascript' src='/js/common.js?1189482083'>
</script>
<script type='text/javascript' language='javascript' src='/js/menus.js?1189482083'>
</script>