JavaScriptを最小限に抑えるためにPHPスクリプトを使用しています。問題は、サーバーが応答するまでにスクリプトが頻繁に 1 秒ほどかかることであり、これは目的をほぼ完全に無効にします。304 を送信しただけでも、応答を送信するのに 1 秒ほどかかる場合があり、その間ブラウザがハングします。
ロード時に、スクリプトは次のように機能します。
- クエリ文字列 var に基づいてロードするファイルを決定します (または、クエリ文字列 var が null の場合は default を使用します)
- ファイルのキャッシュされたコピーが利用可能で最新のものであるかどうかを確認します (これはサーバーに保存されている .txt ファイルです)
- もしそうなら、何もしません。そうでない場合は、キャッシュ ファイルが作成または再作成されます (縮小には JShrink 0.5.1 を使用しています)。
- 最後に、キャッシュ ファイルの etags と last-modified がユーザーが持っているものと一致するかどうかを確認します
- -- その場合は、304 を送信するだけです
- -- そうでない場合は、キャッシュ ファイルに対して readfile を実行します。
これは一貫して行われません。1 回の更新では 1 秒かかる場合があり、次回は 100 ミリ秒かかり、両方とも 304 が返されます。ハード ドライブ (304 を送信する場合でも、キャッシュ ファイルと $fileList 内の任意のファイルに対して filemtime() を実行し、後で現在の etag を生成するためにキャッシュ ファイルに対して md5_file() を実行する必要があります)。
これを回避する方法について何か考えはありますか?関連するコード ブロックを次に示します。
<script type="text/javascript" src="/loadJS.php"></script>
// steps 2 and 3 (check cache, update if necessary, fileList is an array of paths to .js files):
if ( file_exists( $cacheFile ) ) {
$cacheLastModified = filemtime( $cacheFile );
for( $i = 0; $i < sizeof( $fileList ); $i++ ) {
/* check if any files in the list are newer than the cache's last modification date
* if so, cache must be updated
*/
if ( $cacheLastModified < filemtime( $fileList[$i] ) ) {
$outdated = true;
}
}
}
if ( isset( $outdated ) || !file_exists($cacheFile) ) {
// update the cache file now
ob_start();
foreach( $fileList as $file ) {
readfile( $file );
}
$output = ob_get_clean();
include( "includes/JShrink-0.5.1.class.php" );
$output = Minifier::minify($output, array('flaggedComments' => false));
if ( $cacheFileFP = fopen( $cacheFile, "w" ) ) {
if ( fwrite( $cacheFileFP, $output ) ) {
fclose( $cacheFileFP );
} else {
// handle fwrite errors
}
} else {
// handle fopen errors
}
}
// step 4 (function checks etags and modification date):
function fileNotModified ( $file ) {
/* returns false if file NOT modified
* -- or an array of headers if file has been modified
* use two criteria to determine if file has been modified
* a) if-modified-since header vs the file's last-modified time
* b) etag match
* if if-modified-since is the same as file mod time, or etags match
* --- return array of headers to send
* else return false
*
* see http://stackoverflow.com/questions/2000715/answering-http-if-modified-since-and-http-if-none-match-in-php/2015665#2015665
*/
$gmtModifiedTime = gmdate('r', filemtime($file) );
$eTag = md5_file( $file );
$result = false;
if( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) || isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) ) {
if ( $_SERVER['HTTP_IF_MODIFIED_SINCE'] == $gmtModifiedTime || str_replace('"', '', stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])) == $eTag ) {
$result["ETag"] = $eTag;
$result["Last-Modified"] = $gmtModifiedTime;
}
}
return $result;
}
// steps 5 and 6 (304 header or send readfile output):
if ( $headers = fileNotModified( $cacheFile ) ) {
// send the headers and 304 not modified
foreach( $headers as $name=>$value ) {
header( $name . ": " . $value );
}
header('HTTP/1.1 304 Not Modified');
/*exit();*/
} else {
// read and output the cache
header("Last-Modified: " . gmdate("r", filemtime( $cacheFile )) );
header("Etag: " . md5_file( $cacheFile ) );
readfile( $cacheFile );
}