The Webcoda BLOG

Adding timestamps to Drupal stylesheets to ensure an up to date browser cache.

I was getting a bit hacked off with having to explain to clients that while the site is under development they will have to refresh their browser (twice if IE) to get the most up to date stylesheets.

And then there's also the problem of what happens when you update the styles of a live site, do we have to tell all our users to refresh their cache? There has to be a better way.

There is a way using meta tags to ensure that the browser does not use a cache, but with no cache at all we are putting unnecessary demands on the server and increasing the site download time for each page viewed.

My solution to this is not new, and I believe they are using 'asset timestamps' in the next release of Drupal (version 6), but as we are not there yet I thought that I'd show you all how I have done it. The beauty of this method is that your users will only re-download your stylesheet when a new version has been added.

BEWARE! This involves editing a core file (if there is a way to update this method without modifying the core file will someone let me know).

You need to edit /includes/common.inc and add the following text to the drupal_get_css() function.

function drupal_get_css($css = NULL) {
  $output = '';
  if (!isset($css)) {
    $css = drupal_add_css();
  }

  $preprocess_css = variable_get('preprocess_css', FALSE);
  $directory = file_directory_path();
  $is_writable = is_dir($directory) && is_writable($directory) 
    && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) 
    == FILE_DOWNLOADS_PUBLIC);

  foreach ($css as $media => $types) {
    foreach ($types as $type => $files) {
      foreach ($types[$type] as $file => $preprocess) {
	// webcoda addition of timestamp to stylesheets
	$csstimestamp = '?ts=' .filemtime('.' . base_path() . $file);
        if (!$preprocess || !($is_writable && $preprocess_css)) {
          if (!$preprocess && $type == 'module') {
            $no_module_preprocess .= '<style type="text/css" media="'. 
              $media .'">&import "'. base_path() . $file . $csstimestamp .
              '";</style>' ."\n";
          }
          else if (!$preprocess && $type == 'theme') {
            $no_theme_preprocess .= '<style type="text/css" media="'. 
            $media .'">&import "'. base_path() . $file . $csstimestamp .
            '";</style>' ."\n";
          }
          else {
            $output .= '<style type="text/css" media="'. 
            $media .'">&import "'. base_path() . $file . $csstimestamp .
            '";</style>' ."\n";
          }
        }
      }
    }

    if ($is_writable && $preprocess_css) {
      $filename = md5(serialize($types)) .'.css';
      $preprocess_file = drupal_build_css_cache($types, $filename);
      $output .= '<style type="text/css" media="'. 
        $media .'">&import "'. base_path() . $preprocess_file .
        '";</style>'. "\n";
    }
  }

  return $no_module_preprocess . $output . $no_theme_preprocess;
}

My New Blog

in

Hey hey! Here's my new blog... and it works!