上次修改的标头支持不会加快服务器处理速度-想要更多

时间:2018-09-23 作者:GaryL

我刚刚通过推荐为我网站上的一些页面添加了“Last Modified”/“If Modified Since”标题支持here, 但我没有看到明显的客户端页面加载速度提高。我认为这是有道理的,如下所示:

服务器端页面构建过程仍然会发生,但根据客户端请求标头的“上次修改”值(以及其他值),如果客户端不需要,则不会返回服务器构建的页面内容。这对于大型有效负载来说是非常好的,但对于我的用户来说,对于较小的有效负载页面,它可以节省微不足道的时间。(是的,还有其他好处,但这不是我的重点。)

有没有人在Wordpress的这个方向上采取了下一个优化步骤?如果请求“If Modified Since”的请求标头早于“Last Modified”值,那么是否会使页面构建过程短路,并仅返回标头?

简而言之:Is there a way to short circuit the Wordpress page content generation process, and return the response header only?

…或者…是否有人知道下一个不同/更好的优化步骤?

从我对WP的部分理解来看,您似乎需要一个钩子来拦截/替换页面模板处理,并且主要的“问题”是,如果(其他)可能被中断的插件也想要操作响应头。

2 个回复
SO网友:Mark Kaplun

要使基于协议的优化有效,您需要有大量的流量,即使如此,即使它确实起作用,您也不太可能获得多少收益。

大多数人都是您网站的第一次用户,而浏览器只有有限的空间来存储用户访问的所有页面的上次更新时间信息。

但是,即使你真的收到这样的请求,你怎么确切地知道上次更新是什么时候?wordpress对这个问题的最佳答案是最新发布帖子的发布时间,这可能根本不代表主题更改或任何其他设置更改发生的时间。但即使是这样一个天真的假设,您仍然需要加载wordpress并执行至少两个DB查询。您可能会得到一些改进,但不如首先使用对象缓存或页面缓存。

而在现实世界中,大部分的缓慢都是由于页面上的JS/CSS/媒体,如果它没有被缓存(除非你是facebook,否则它不太可能被缓存),那么即使“最后发布”的东西起作用了,你的页面仍然会加载缓慢。

SO网友:GaryL

我在回答我自己的问题。也许它对其他人有用。

Short answer: 您可以通过以下方式缩短页面生成过程wp_die()wp_send_json().

但因为我不想发送500状态,所以它消除了wp\\u die(),因为我想发送html而不是json,所以它消除了wp\\u send\\u json()。因此,我复制了;修改了wp_send_json() source 生成以下内容:

function wp_send_html( $response = null, $status_code = null ) {
    @header( \'Content-Type: text/html; charset=\' . get_option( \'blog_charset\' ) );
    if ( null !== $status_code ) {
        status_header( $status_code );
    }
    if ($response) {
        echo $response; 
    }
    die;
};
在我的代码中,在我确定请求与之前的请求保持不变后,我调用:

wp_send_html(null, 304);
。。。它发送一个304响应,包括任何具有设置的html响应头和一个空正文。

Result: ~75% page load time savings

在我使用的单个帖子中,我将响应时间从大约4-5秒减少到了1.0-1.3秒。

Longer answer:

从@Mark的帖子中,我需要考虑的主要事情是帖子的最后一次更改,以及任何主题或其他全局元素的最后一次更改。我只处理单页/贴子页,并且我添加了$MIN_UPD_DATE 全局位于我的功能顶部。php with I will update when I do global/style changes(是的,我知道这有点麻烦)。

我的函数中更完整的代码。php如下:

// Update this on sitewide changes
$MIN_UPD_DATE = DateTime::createFromFormat(\'M d Y H:i:s\', \'Sep 01 2018 01:01:01\');

// For web pages and single post pages - note the last changed date
    // Thanks to: https://wordpress.stackexchange.com/questions/172966/if-modified-since-http-header
    // This will support clients sending HTTP header: If-Modified-Since 
function handle_modified_since_header() {
    global $MIN_UPD_DATE;
    //Check if we are in a single post of any type (archive pages have no modified date)

    if( is_singular() ) { // excludes multi-post pages
        $post_id = get_queried_object_id();
        if( $post_id ) {
            header("Cache-Control: public");  
            // inherited/default was: Cache-Control: no-cache, must-revalidate, max-age=0

            $postModTime = new DateTime(get_the_modified_time(\'D, d M Y H:i:s\', $post_id));
            if ($MIN_UPD_DATE > $postModTime) {
                $postModTime = $MIN_UPD_DATE;
            };
            header("Last-Modified: " . $postModTime->format("D, d M Y H:i:s") . " GMT" );
            return true;    // can use modified date to expire page
        }
    }
    return false;   // can NOT use modified date to expire page
};

// Checks single post & page entries for a Post Modified Date 
//  after the http request header: IF_MODIFIED_SINCE
//     or after the MIN_UPD_DATE
//  else, on any missing elements, assumes that request is expired.
function is_request_expired() {
    global $MIN_UPD_DATE;
    $MOD_SINCE   = \'HTTP_IF_MODIFIED_SINCE\';
    $DATE_FMT    = \'D, d M Y H:i:s O\';
    $postModTime = null;
    $isExpired   = true;
    $httpLastUpdate    = null;

    if (!isset( $_SERVER[$MOD_SINCE] )) {  // Quit on no http last mod date
        return $isExpired;
    };

    $httpLastUpdate = DateTime::createFromFormat($DATE_FMT, $_SERVER[$MOD_SINCE]);
    if (!$httpLastUpdate) {       // Quit on can\'t decode last mod date
        return $isExpired;
    }

    $post_id = get_queried_object_id(); // Get Post last modified date
    if( $post_id ) {
        $postModTime = new DateTime(get_the_modified_time(\'D, d M Y H:i:s\', $post_id));
    };

    if ($postModTime) {
        // http last-mod-date is before post-list-mod-date or before min-upd-date
        $isExpired = ($httpLastUpdate < $postModTime) || ($httpLastUpdate < $MIN_UPD_DATE);
    };
    return $isExpired;
}

function send_on_not_expired_single( $wp_query ) {      
    if ($_SERVER[\'REQUEST_METHOD\']!==\'GET\') {  // ignore for non-GET requests
        return $wp_query;
    }

    $use_modified_since_rule = handle_modified_since_header(); // conditionally set Last-Modified http header
    if ($use_modified_since_rule) {
        $is_expired = is_request_expired();
        if (!$is_expired) {
            wp_send_html(null, 304);
        };
    };
    return $wp_query;
}
add_filter( \'parse_query\', \'send_on_not_expired_single\', 200);

/**
 * Send an HTML response back to an html request.
 *              patterned on the v4.9.8 WP codex wp_save_json
 *              from: https://core.trac.wordpress.org/browser/tags/4.9.8/src/wp-includes/functions.php#L3179
 *
 * @param mixed $response    Variable (usually an array or object),
 *                           then print and die.
 * @param int   $status_code The HTTP status code to output.
 */
function wp_send_html( $response = null, $status_code = null ) {
    @header( \'Content-Type: text/html; charset=\' . get_option( \'blog_charset\' ) );
    if ( null !== $status_code ) {
        status_header( $status_code );
    }
    if ($response) {
        echo wp_json_encode( $response );   
    }
    die;
};
最后,根据一些评论/建议,我确实查看了一些缓存插件。虽然其中一些插件在更新站点演示文稿时有很好的“上次修改日期”检查/更新逻辑(我没有),但我查看的那些插件要么专门将登录用户排除在缓存之外,或者对登录的用户有很大的限制,从而消除了他们对我的关注点的有用性。

结束

相关推荐

将HTTP请求重定向到HTTPS请求

我正在运行一个不在Wordpress上的网站,它是由另一个开发人员使用自定义框架构建的,太可怕了。这就是我现在发疯的原因。目前,我需要将用户对我们网站的请求重写如下:我尝试了很多没有运气的事情。%{SERVER\\u PORT}80是我尝试过的事情之一。下面是我的。htaccess的内容:Options +FollowSymlinks DirectoryIndex home.html index.php Options -Indexes Rewrite