Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

Customising the CMS /

Compressing static content


Reply


2 Posts   1390 Views

Avatar
garyw

Community Member, 1 Post

4 April 2010 at 8:17am

Edited: 04/04/2010 8:18am

I found a way of speeding up the static publisher a bit by adding a compressed version of each cached file to the cache. The reason why I did this, and didn’t simply use the mod_deflate module or the ob_gzhandler function, was due to the following:

  • mod_deflate and ob_gzhandler dynamically compress data. This is great for dynamic content, but we’re working with static content. It doesn’t make sense to compress a file over and over when we could just compress it once.
  • Some Web hosts may not have the mod_deflate module available.

Creating compressed versions of static content is a bit tricky, since no function really exists in PHP to generate the exact deflated content that Web browsers expect. Here’s a snippet of the code I used:

cms/code/staticpublisher/FilesystemPublisher.php

class FilesystemPublisher extends StaticPublisher {
…
/**
* Create a second set of cached files that are compressed using the PHP function gzcompress().
* By default, this is false, but so many browsers support gzip encoding that you should seriously consider setting this to true.
*/
public static $create_compressed_files = true;
…
$files[] = array(
'Content' => $content,
'Folder' => dirname($path).'/',
'Filename' => basename($path),
);

// Should we create a compressd version of the file?
if (self::$create_compressed_files && $this->fileExtension != 'php') {
$gzsize = strlen($content);
$gzcrc = crc32($content);
$gzdata = gzcompress($content);
$gzdata = substr($gzdata, 0, strlen($gzdata) - 4);

$files[] = array(
'Content' => "\x1f\x8b\x08\x00\x00\x00\x00\x00" . $gzdata . pack('V', $gzcrc) . pack('V', $gzsize),
'Folder' => dirname($path).'/',
'Filename' => basename($path).'.gz',
);
}
…

Like I said… a bit tricky. Thankfully this code will only be run when the static cache is generated.

Here’s the changes made to sapphire/static-main.php:

…
// Look for the file in the cachedir
$file = preg_replace('/[^a-zA-Z0-9]/si', '_', trim($_SERVER['REQUEST_URI'], '/'));
$file = $file ? $file : 'index';

$acceptCompressed = (preg_match('/gzip/', $_SERVER["HTTP_ACCEPT_ENCODING"]));
$fileExtension = '.html';
$compressedExists = ($acceptCompressed && file_exists('../cache/'.$cacheDir.$file.$fileExtension.'.gz'));

// If a compressed version of this file exists, output a header that says we're about to send compressed data.
if ($compressedExists)
{
header('Content-Encoding: gzip');
$fileExtension .= '.gz';
}

$gmNow = @gmdate('D, d M Y H:i:s \G\M\T');

if ($compressedExists || file_exists('../cache/'.$cacheDir.$file.$fileExtension)) {
$fileToSend = '../cache/'.$cacheDir.$file.$fileExtension;
header('X-cache: hit at '.$gmNow);
echo file_get_contents($fileToSend);
} elseif (file_exists('../cache/'.$cacheDir.$file.'.php')) {
header('X-cache: hit at '.$gmNow);
include_once '../cache/'.$cacheDir.$file.'.php';
if ($cacheDebug) echo "<h1>File was cached</h1>";
} else {
header('X-cache: miss at '.$gmNow . ' on ' . $cacheDir . $file);
// No cache hit... fallback!!!
include 'main.php';
if ($cacheDebug) echo "<h1>File was !NOT! cached</h1>";
}
…

It’s somewhat of a cheap hack but it works. On average, it reduces HTML bandwidth by about 80%, and you don’t even need to mess with the Apache or PHP configuration.

Avatar
kaanuni

Community Member, 22 Posts

13 October 2012 at 2:02am

Is there an updated way to do this in ss3?