While working with Anthony Short’s amazing CSScaffold, the idea came up to have a similar compressing and caching mechanism for javascript. For this little experiment I took Douglas Crockford’s javascript compressor, ported to php by Ryan Grove (visit JSMin’s repository on github for more infos) and clashed it up with some lightweight additional code. It is pretty easy to integrate it into running applications or frameworks, for example simply put it into cakePHP’s javascript-directory. There is no need to change something in your application’s code. You can try the result yourself: Javascript Cache and Compressor.
Just as easy as possible:
class Cache {
public static function is_expired($file, $cache_file) {
if ( !file_exists($cache_file) ) return true;
return ( filemtime($cache_file) <= filemtime($file) );
}
public static function write($cache_file, $content) {
if( !is_dir(dirname($cache_file)) ) {
mkdir(dirname($cache_file), 0777, true);
chmod(dirname($cache_file), 0777);
}
file_put_contents($cache_file, $content);
chmod($cache_file, 0777);
touch($cache_file, time());
}
public static function read($file, $cache_file) {
if ( !self::is_expired($file, $cache_file) ) return file_get_contents($cache_file);
return false;
}
public static function lastmod($file, $cache_file) {
if ( file_exists($cache_file) ) return filemtime($cache_file);
return filemtime($file);
}
}
Really self explaining. It provides some levers for developing / debugging and the only configuration that has to be made: the javascript base-dir.
/**
* Set to FALSE to prevent error_reporting
*/
define('DEBUG', FALSE);
/**
* Set to TRUE to enable javascript-compress via jsmin
*/
define('MINIFY', TRUE);
/**
* Path to javascript-directory
*/
define('BASE_DIR', '/app/webroot/js/');
/**
* Set to FALSE to disable caching
*/
define('CACHE', TRUE);
/**
* Set to FALSE to force a recache
*/
define('FORCE_RECACHE', FALSE);
/**
* Relative path to cache-directory
*/
define('CACHE_DIR', './cache/');
It’s task is to tie JSMin and cache together with some logic using the config-values as easy as possible:
if ( DEBUG === false ) { error_reporting(0); } else { error_reporting(E_ALL | E_NOTICE); }
$result = false;
if ( CACHE && !FORCE_RECACHE ) $result = Cache::read(FILE, CACHE_FILE);
if ( $result === false ) {
$result = file_get_contents(FILE, CACHE_FILE);
if ( MINIFY ) $result = JSMin::minify($result);
if ( CACHE && MINIFY ) Cache::write(CACHE_FILE, $result);
}
header('Content-Type: text/javascript');
header("Vary: User-Agent, Accept");
header('Last-Modified: '. gmdate('D, d M Y H:i:s', Cache::lastmod(FILE, CACHE_FILE)) .' GMT');
echo $result;
Links all javascript-files to index-file and by that way uses apache’s mod_deflate for a bit more performance.
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_URI} \.js$
RewriteRule ^(.+)$ jsmin/index.php?request=%{REQUEST_URI}
</IfModule>
Thats all. I’m sure there is a lot more room for improvement and I’ll love to read your issues!
return ( self::lastmod($cache_file) <= filemtime($file) );
}
public static function write($cache_file, $content) {
if( !is_dir(dirname($cache_file)) ) {
mkdir(dirname($cache_file), 0777, true);
chmod(dirname($cache_file), 0777);
}
file_put_contents($cache_file, $content);
chmod($cache_file, 0777);
touch($cache_file, time());
}
public static function read($file, $cache_file) {
if ( !self::is_expired($file, $cache_file) ) return file_get_contents($cache_file);
return false;
}
public static function lastmod($file, $cache_file) {
if ( file_exists($cache_file) ) return filemtime($cache_file);
return filemtime($file);
}
}
No Comments