toscho.design

Frisches Layout

Wie alle guten Dinge ist ein Stylesheet kein Zustand, sondern ein Prozeß. Hier ein Farbton, da ein neues Hintergrundbild oder schon wieder ein neuer Browserbug – immerzu muß es angepaßt und verbessert werden.

Das Problem: Die Leser laden immer noch die alte Version aus ihrem Cache oder dem Proxy des Providers, weil die Adresse ja gleich bleibt.

Genau da – an der Adresse – setze ich an. Wer mal einen Blick unter die Haube wirft, sich also meinen Quellcode ansieht, wird dieses entdecken:

<link 
  rel="stylesheet" 
  media="screen,projection" 
  href="/wp-content/themes/toscho/css?d=1229632675" 
  title="screen+projection" 
  type="text/css"
>

In meinem Template – ich verwende hier WordPress – steht:

<link rel="stylesheet" media="screen,projection" href="<?php
  bloginfo('template_directory');
?>/css?d=<?php
  echo filemtime(TEMPLATEPATH . '/screen.css');
?>" title="screen+projection" type="text/css">

Die Funktion filemtime() gibt das Datum der letzten Änderung als UNIX-Timestamp zurück, und ich hänge es einfach als Parameter an.

So müssen sich die Browser immer das frische Stylesheet holen, und ich muß mich nicht mehr darum kümmern, wenn ich etwas ändere. Der Aufruf geht an ein PHP-Script, das mein Stylesheet zusammensetzt und sich auch um die HTTP-Kommunikation kümmert, also auch clientseitiges Caching ermöglicht.

3 Kommentare

  1. Frank am 16.01.2009 · 21:46

    Alternativ habe ich eine kleine Funktion in der functions.php des Thems, die sich darum kümmert.

    /**
     * Smart cache-busting
     * cacht css des Themes
     */
    if ( !function_exists('fb_css_cache_buster') ) {
    	function fb_css_cache_buster($info, $show) {
    		if ($show == 'stylesheet_url') {
    			
    			// Is there already a querystring? If so, add to the end of that.
    			if (strpos($pieces[1], '?') === false) {
    				return $info . "?" . filemtime(WP_CONTENT_DIR . $pieces[1]);
    			} else {
    				$morsels = explode("?", $pieces[1]);
    				return $info . "&" . filemtime(WP_CONTENT_DIR . $morsles[1]);
    			}
    		} else {
    			return $info;
    		}
    	}
    	
    	add_filter('bloginfo_url', 'fb_css_cache_buster', 9999, 2);
    }
    
  2. Thomas Scholz am 16.01.2009 · 22:14

    Das sieht sehr … kompliziert aus.
    Hat WordPress etwas aus deinem Code geklaut, oder sehe ich einfach nicht, woher $pieces kommt?

    Ich benutze übrigens bloginfo('stylesheet_url') nicht, weil ich mich a) ästhetisch dagegen auflehne, ein Stylesheet »style.css« zu nennen, und b) je Ausgabemedium ein separates Stylesheet verwende.
    Außerdem zerstört der angehängte Querystring ja das Validieren des clientseitigen Caches durch den Server, wenn man nicht nachhilft.
    Klick mal beim Websniffer auf den ETag – da sollte doch kein 200 zurückkommen, sondern 304 (Last-Modified ist immer zusätzliches Problem, wenn die Serverzeit irgendwie hakt).

    Deshalb fange ich alle Stylesheet-Aufrufe lieber mit einem eigenen CSS-Skript ab (darüber schreibe ich vielleicht demnächst mal was), das meine HTTP-Klasse aufruft und dann anstelle des Apachen den Cache validiert.

    Hm, ich muß demnächst mal pre in diesem Formular nachrüsten …

  3. Kaiser am 31.12.2010 · 12:27

    Hello Thomas!

    filemtime(): Kluge Sache! Hab bisher bei der dev-version (local/staging) immer rand() genommen und dann erst bei live auf meine Versionskonstante verwiesen. Danke für den Tip!

    FJ.