为什么缓存资源可能需要很长时间才能在浏览器中呈现?

时间:2013-07-30 19:07:11

标签: javascript css caching

我有一个奇怪的问题。我在PHP中生成css和js,代码在浏览器中正确缓存,但是从图像中可以看到渲染需要很长时间。

enter image description here

我可以确认缓存是否正常工作,因为没有对服务器进行调用(我有firePHP),你可以看到这里的内容http://www.nwkidsmagazine.com/kids-activities-and-things-to-do/

有人对此有解释吗?

编辑 - 这是调用渲染css的函数

public function render_css() {
    header( 'HTTP/1.1 200 OK' );
    header( 'Content-Type: text/css', true, 200 );
    // Aggressive caching to save future requests from the same client.
    $etag = '"' . md5( __FILE__ . $_GET[self::GET_VARIBALE_NAME] ) . '"';
    header( 'ETag: ' . $etag );
    $max_age = 31536000;
    header(
        'Expires: ' .
        gmdate(
            'D, d M Y H:i:s',
            Ai1ec_Time_Utility::current_time() + $max_age
        ) .
        ' GMT'
    );
    header( 'Cache-Control: public, max-age=' . $max_age );
    if (
        empty( $_SERVER['HTTP_IF_NONE_MATCH'] ) ||
        $etag !== stripslashes( $_SERVER['HTTP_IF_NONE_MATCH'] )
    ) {
        // compress data if possible
        $zlib_output_handler = ini_get( 'zlib.output_handler' );
        if (
            true === extension_loaded( 'zlib' ) &&
            ! in_array( 'ob_gzhandler', ob_list_handlers() ) &&
            ! in_array(
                strtolower( ini_get( 'zlib.output_compression' ) ),
                array( '1', 'on' )
            ) &&
            empty( $zlib_output_handler )
        ) {
            ob_start( 'ob_gzhandler' );
            header( 'Content-Encoding: gzip' );
        } else {
            ob_start();
        }
        $content = $this->get_compiled_css();
        echo $content;
        ob_end_flush();
    } else {
        // Not modified!
        status_header( 304 );
    }
    // We're done!
    ai1ec_stop( 0 );
}

这是针对js

public function render_js() {
    header( 'HTTP/1.1 200 OK' );
    header( 'Content-Type: application/javascript; charset=utf-8', true, 200 );
    // Aggressive caching to save future requests from the same client.
    $etag = '"' . md5( __FILE__ . $_GET[self::LOAD_JS_PARAMETER] ) . '"';
    header( 'ETag: ' . $etag );
    $max_age = 31536000;// One Year
    header(
        'Expires: ' .
        gmdate(
            'D, d M Y H:i:s',
            Ai1ec_Time_Utility::current_time() + $max_age
        ) .
        ' GMT'
    );
    header( 'Cache-Control: public, max-age=' . $max_age );
    if (
        empty( $_SERVER['HTTP_IF_NONE_MATCH'] ) ||
        $etag !== stripslashes( $_SERVER['HTTP_IF_NONE_MATCH'] )
    ) {
        // compress data if possible
        $zlib_output_handler = ini_get( 'zlib.output_handler' );
        if (
            true === extension_loaded( 'zlib' ) &&
            ! in_array( 'ob_gzhandler', ob_list_handlers() ) &&
            ! in_array(
                strtolower( ini_get( 'zlib.output_compression' ) ),
                array( '1', 'on' )
            ) &&
            empty( $zlib_output_handler )
        ) {
            ob_start( 'ob_gzhandler' );
            header( 'Content-Encoding: gzip' );
        } else {
            ob_start();
        }

        $js_path = AI1EC_ADMIN_THEME_JS_PATH . DIRECTORY_SEPARATOR;
        $common_js = '';
        $page_to_load = $_GET[self::LOAD_JS_PARAMETER];

        if ( $_GET[self::IS_BACKEND_PARAMETER] === self::TRUE_PARAM ) {
            $common_js = file_get_contents( $js_path . 'pages/common_backend.js' );
        } else if( $page_to_load === self::EVENT_PAGE_JS ||
            $page_to_load === self::CALENDAR_PAGE_JS || 
            $page_to_load === self::LOAD_ONLY_FRONTEND_SCRIPTS ) {
            if ( $page_to_load === self::LOAD_ONLY_FRONTEND_SCRIPTS &&
                true === self::$frontend_scripts_loaded ) {
                return;
            }
            if ( false === self::$frontend_scripts_loaded ) {
                $common_js = file_get_contents( $js_path . 'pages/common_frontend.js' );
                self::$frontend_scripts_loaded = true;
            }

        }
        // create the config object for require js
        $require_config = $this->create_require_js_config_object();
        // load require
        $require = file_get_contents( $js_path . 'require.js' );

        // get jquery
        $jquery = $this->get_jquery_version_based_on_browser( 
            $_SERVER['HTTP_USER_AGENT']
        );
        // load the script for the page

        $page_js = '';
        if ( $page_to_load !== self::LOAD_ONLY_BACKEND_SCRIPTS &&
             $page_to_load !== self::LOAD_ONLY_FRONTEND_SCRIPTS
        ) {
            $page_js = file_get_contents( $js_path . 'pages/' . $page_to_load );
        }


        $translation = $this->get_frontend_translation_data();
        $permalink = get_permalink( $this->settings->calendar_page_id );

        $translation['calendar_url'] = $permalink;

        $tranlsation_module = $this->create_require_js_module( 
            self::FRONTEND_CONFIG_MODULE, 
            $translation 
        );
        $config = $this->create_require_js_module(
            'ai1ec_config',
            $this->get_translation_data()
        );
        echo $require . $require_config . $tranlsation_module . 
                $config . $jquery . $page_js . $common_js;
        ob_end_flush();
    } else {
        // Not modified!
        status_header( 304 );
    }
    // We're done!
    ai1ec_stop( 0 );
}

1 个答案:

答案 0 :(得分:3)

要说没有对服务器进行任何呼叫是不准确的。 A response of 304表示已向服务器发出请求,但服务器指示资源尚未修改,因此无需重新发送资源。

然而,它仍然需要等待服务器响应那个304.在我对页面的快速测试中,有几个资源在服务器响应之前花了很长时间那304。

调查结果

在我的测试中,花费最多的时间只是等待服务器响应初始请求。

但是,由于缓存标头的设置方式,有一些资源总是会被重新请求。

例如,这个资源:

http://www.nwkidsmagazine.com/?ai1ec_render_js=calendar.js&is_backend=false&is_calendar_page=true&ver=1.11.2-pro

始终将其Expires标头设置为当前日期时间戳。 因此,客户端将始终从服务器请求它。

它恰好也是最大的罪犯,有时需要花费5秒来回应最初的请求。

如果这是一个动态资源,那么我建议用一种更简单,更快速的机制来确定ETag由于ETag应该始终优先,因此它确实需要快速操作。