【发布时间】:2015-01-14 02:31:19
【问题描述】:
我们的应用程序在 head 标签中有很多 CSS 和 JS,为了提高感知页面加载速度,我希望页面尽快开始获取外部内容,即使在等待服务器提供其他内容。基本上我的目标是让浏览器在等待正文内容交付时开始获取 head 标签中的 CSS 和 JS。
所以在主布局页面中,我尝试在渲染头部标签后刷新缓冲区(在 php.ini 中关闭了 output_buffering):
<?php ob_start(); ?>
<head>
<?php
// A bunch of function calls to render tags for external style sheets and JS
?>
</head>
<?php ob_end_flush(); ?>
<body>
Body content rendered here . . .
</body>
这基本上没有效果。当我查看 Chrome 中的网络活动时,我看到 head 标签和 body 标签都在一个响应中交付,只有在完成加载之后,其他资源才开始按顺序加载,而不是像我预期的那样并行加载。
我尝试了许多其他组合,但运气不佳。我还读到刷新输出缓冲区后需要调用 flush() 但这给了我奇怪的结果:页面只显示了一堆奇怪的外来字符(也许它试图显示二进制文件或其他东西?) .
我什至尝试只在 head 和 body 标签之间调用 flush() ,但这引发了一个错误,告诉我我正在尝试修改已经发送的 headers,所以没有做任何事情对我也有用。
然后我尝试查看是否存在特定于 Zend Framework 的解决方案。有人告诉我我正在尝试做的事情是不可能的,因为 ZF 从内存中的模板渲染整个页面,因此它不能在渲染过程中被刷新并发送回浏览器,而 ZF 基本上忽略 PHP 的 output_buffering 配置值。
我想我已经用尽了所有可能的组合刷新功能,所以我想知道是否有其他人遇到过类似的问题以及方法是什么。
服务器版本:Apache/2.2.22 (Ubuntu)
(顺便说一句,是的,我知道应该在页面底部加载 JS,但这不是我将其放入 head 标签中的要求)
更新 1
当我尝试以下操作时,我得到了我想要的,部分:
<?php ob_start('ob_gzhandler'); ?>
<head>
<?php
// A bunch of function calls to render tags for external style sheets and JS
?>
</head>
<?php ob_end_flush(); ?>
<body>
Body content rendered here . . .
</body>
我为 ob_start 添加了一个回调到 ob_gzhandler。这样做会返回一个包含 head 标签的响应,没有正文。这很好,因为一旦 head 标签到来,资源就会开始加载,但 body 标签永远不会到来,页面基本上是空白的。就好像告诉它刷新刷新缓冲区,但是脚本在完成执行后再也不会刷新。
我已经在布局脚本的末尾明确添加了对 ob_flush(和其他变体)的调用,但它们要么不做任何事情,要么抱怨没有要刷新的缓冲区(可能是因为我之前调用了 ob_end)。
【问题讨论】:
标签: php zend-framework flush output-buffering