1

我正在使用 PHP 脚本来最小化 javascript。问题是脚本在服务器响应之前经常需要一秒钟左右的时间,这几乎完全违背了目的。即使只是发送一个 304,有时仍然需要一秒钟左右的时间来发送响应,在此期间浏览器处于挂起状态。

加载时,脚本功能如下:

  1. 根据查询字符串 var 确定要加载的文件(或文件)(如果查询字符串 var 为空,则使用默认值)
  2. 检查文件的缓存副本是否可用并且是最新的(这是存储在服务器上的 .txt 文件)
  3. 如果是这样,什么也不做。如果没有,则创建或重新创建缓存文件(我使用 JShrink 0.5.1 进行缩小)
  4. 最后,检查缓存文件的 etags 和 last-modified 是否与用户的匹配
  5. -- 如果是这样,只需发送 304
  6. -- 如果没有,在缓存文件上做一个 readfile

它不会始终如一地执行此操作 - 一次刷新可能需要一秒钟,下一次大约需要 100 毫秒,两者都返回 304。由于不一致,我最好的猜测是延迟访问缓存文件硬盘驱动器(即使发送 304,它仍然必须对缓存文件和 $fileList 中的任何文件执行 filemtime(),然后对缓存文件执行 md5_file() 以生成当前 etag)。

关于如何解决这个问题的任何想法?以下是一些相关的代码块:

<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 );
}
4

1 回答 1

0

我没有测试以下代码,但这是你应该做的:

if(!file_exists($js_path_cache) || filemtime($js_path_cache) < filemtime($js_path) {
  // MINIFY YOUR JS HERE
}
于 2013-09-13T19:12:54.010 回答