如何协调 gzip 压缩和 index.php 标头的刷新


How to reconcile gzip compression and the flushing of the header of index.php

我有一个相当大的索引.php文件(约500kB),其中存在大量逻辑和数据库查询(索引.php进入客户端约为200kB)。
我想做的是首先使用 gzip 压缩文件,我只需在.htaccess文件中添加SendOutputFilter即可。现在,由于文件对于服务器来说处理起来非常大,TTFB 可能需要一段时间,因此我想在查看查询之前向用户发送文件的标头,以便浏览器将发现图像、css 和 js(它们也很大)并开始下载而不是闲置等待整个索引.php在服务器上处理(我想要像 Google 这样的东西搜索确实如此。它在加载整个页面之前开始下载 png(并且页面被压缩))。
我做了一些查询,但找不到任何直接的解决方案。我发现要么我禁用 gzip 并使用刷新,要么使用 gzip 但不刷新。
但正如你在我的案例中看到的那样,我需要两者,我知道这可以以某种方式完成。可能有一些解决方法。
这就是大型现代网站已经做到的方式,所以我想知道怎么做。

幸运的是我错了。即使GZIP需要完全下载才能解压缩,您也不必只发送一个chunk。您可以发送多个单独的chunks,其中每个都是单独编码的。

这意味着浏览器需要完全下载chunk浏览器,然后它可以解压缩它并开始解析html 。同时,它正在下载chunk两个。

通过多次刷新进行渐进式渲染是一篇很好的文章,解释了它是如何工作的。然而,它不是PHP处理的,而是服务器/apache处理的。

查看如何让 PHP 为您需要做的PHP部分生成分块响应。

要使GZIP工作与您的服务器的设置方式有关,为了帮助,您最好的选择是服务器故障

这并没有解决GZIP和flush的问题,而是针对您有关预加载css,html等的问题量身定制的PHP脚本和页面设计。

您可能需要考虑在两个脚本之间拆分索引.php工作负载,首先加载 html 用于显示目的,然后使用 ajax 异步请求"较重"的任务,然后更新屏幕的某些部分。这将允许CSS和所有其他任务首先完成工作,然后是运行时间更长的任务以稍后显示其结果。

为了完成这个开始,使用一个"轻量级"索引.php文件,具有基本的网页html和显示逻辑,以及像$(window).load(function(){ //ajax call to heavier heavy_index.php script and screen updating from response })这样的事件/触发器,它将允许页面完全呈现,然后在加载后调用更重的东西。

这给出了一个简单的例子:

索引.php

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="/my_css.css">
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
        <script type="text/javascript">
            $(window).load(
                function () {
                    alert("About to load more content");
                    $.ajax({
                        url: "/heavy_index.php",
                        success: function (html_data) {
                            $("#content_loaded_later").html(html_data);
                        }
                    });
                });
        </script>
    </head>
    <body>
        <div class='content_initial'  ><span>Content initially loaded</span></div>
        <div class='content_later' id='content_loaded_later'>loading...</div>
    </body>
</html>

heavy_index.php

<?php
echo "resulting content from heavier workload";
?>

my_css.css

.content_initial
{
border:1px solid red; width:120px; height:120px;
margin:10px;
}
.content_later
{
border:1px solid green; width:120px; height:120px;
margin:10px;
}

你可能还想看看这篇文章 预加载CSS/Javascript 而不执行

希望这有所帮助。

据我所知,Apache内部没有办法强制将内容提前输出到浏览器。但是,可以从PHP执行此操作。请注意,在 PHP 中,输出缓冲区可以分层,因此您可能需要....

而 (ob_get_level()) ob_end_flush();

这会将数据发送回 Apache,而不会关闭标准输出。在没有其他并发症的情况下,这将触发对浏览器的分块响应。但mod_deflate输出过滤器也会缓冲数据 - DeflateBufferSize - 默认情况下为 8kb。如果你的

(不是你的标题!)超过这个大小,它将位于缓冲区中,直到它被更多内容推出。您可以减小缓冲区的大小,并且可以填充内容以填充它 - 实际上您应该同时使用这两种方法。

由于其他人说这是不可能的(不是 - 尝试一下)并描述了使用 Ajax 加载页面,您可能想看看 PJAX。在非常繁重的javascript网站上使用它有很大的优势。