Skip to content

Instantly share code, notes, and snippets.

@meglio
Created September 19, 2012 11:41
Show Gist options
  • Save meglio/3749224 to your computer and use it in GitHub Desktop.
Save meglio/3749224 to your computer and use it in GitHub Desktop.
js.php Joins and minifies js files from html template into cached.js and controls Cache-Control headers based on mtime of all files engaged
<?php
header('Content-Type: text/javascript');
$cacheFile = __DIR__.'/js/cached.js';
$listFile = __DIR__.'/js/cached-list.txt';
$htmlFile = __DIR__.'/tmpl/web/html5.twig';
$htmlTime = filemtime($htmlFile);
$cacheTime = file_exists($cacheFile)? filemtime($cacheFile) : 0;
# Update list of cached js files if it does not exist yet or if html file changed
if (!file_exists($listFile) || filemtime($listFile) < $htmlTime)
{
$html = file_get_contents($htmlFile);
preg_match('|<body.+</body\s*?>|is', $html, $m);
$body = $m[0];
$regex = <<<REGEX
/{{\s*js\s*\(\s*('|")(?P<link1>[^)'"]+)('|")\s*\)\s*}}|<script[^>]+src\s*=\s*('|")(?P<link2>.+?)('|")/is
REGEX;
preg_match_all($regex, $body, $matches, PREG_SET_ORDER);
$files = [];
foreach($matches as $match)
{
$link = empty($match['link1'])? $match['link2'] : $match['link1'];
if (strtolower(substr($link, -3)) == '.js' && file_exists($filePath = __DIR__.$link))
$files[] = $filePath;
}
if (file_exists($listFile))
unlink($listFile);
file_put_contents($listFile, join("\n", $files));
$forceUpdate = true;
}
if (!file_exists($cacheFile))
$forceUpdate = true;
# ?update=1 in DEBUG mode forces update, even if cached.js already exists
if (!isset($forceUpdate) && file_exists($cacheFile) && array_key_exists('update', $_GET))
{
$configFile = __DIR__.'/proj/config.php';
if (file_exists($configFile) && is_readable($configFile))
{
require $configFile;
if (defined('DEBUG') && DEBUG)
$forceUpdate = true;
}
}
# Update if filemtime() for any of files from the list is changed
if (!isset($forceUpdate))
{
if (!isset($files))
$files = file($listFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$maxTime = 0;
foreach($files as $f)
$maxTime = max($maxTime, filemtime($f));
if ($maxTime > $cacheTime)
$forceUpdate = true;
}
# Generate cached.js
if (isset($forceUpdate))
{
if (!isset($files))
$files = file($listFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$js = '';
foreach($files as $file)
$js .= file_get_contents($file)."\n";
require(__DIR__.'/proj/utils/JSmin.php');
$result = JSMin::minify($js);
if (file_exists($cacheFile))
unlink($cacheFile); // unlink clears the cache automatically
file_put_contents($cacheFile, $result);
$cacheTime = filemtime($cacheFile);
}
# Output
if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $cacheTime)
{
header('HTTP/1.1 304 Not Modified');
die();
}
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $cacheTime).' GMT');
$offset = 3600 * 24 * 30;
header("Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . ' GMT');
header("Cache-Control: public, max-age=3600, must-revalidate");
die(file_get_contents($cacheFile));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment