大多数 WordPress 主题在评论线程中显示用户 Gravatar。这是一种显示用户图像的方式,与使用的电子邮件地址相关联。这是一个不错的功能,并且如今几乎已成为一种预期的设计模式。
但是,每个 Gravatar 都是一个单独的 HTTP 请求,就像任何其他图像一样。一个有 50 条评论的评论线程意味着 50 个 HTTP 请求,而且它们并不总是特别小的文件。哎呀。
让我们延迟加载它们。
概念
延迟加载的想法是,除非图像可见,否则您根本不请求图像(没有 HTTP 请求)。这意味着,通过 JavaScript,我们已经确定图像可见。

为了停止对尚未查看的图像的 HTTP 请求,我们需要直接获取标记。如果 HTML 中存在 <img src="">
,则基本上无法阻止浏览器尽快下载该图像,无论是否可见。因此,我们需要删除该 src
,并在准备好时将其放回。
等等
这里值得暂停一下,因为我们已经进入了一些模糊的领域。
通过删除这些图像的 src
,并且只使用 JavaScript 将其放回,我们已经决定愿意发送略微无效的 HTML,并且完全依赖脚本下载和执行才能看到这些图像。
我对此表示赞同。主要是因为 Gravatar 仅仅是增强功能。如果它们永远不会显示出来,也没什么大不了的。我不是大多数 JavaScript 辩论的强硬派,但这似乎是一个特别清楚的案例,我们可以毫无顾虑地依赖 JavaScript。
修改 HTML
这是我们将进行的更改
<!-- Normal image. No beating the browser preloader. -->
<img src="https://gravatar.whatever..." alt="" />
<!-- Let's change to this, which won't download anything. -->
<img data-src="https://gravatar.whatever..." alt="" />
虽然 <img>
上缺少 src
在技术上是无效的 HTML。但它几乎肯定无关紧要,因为它不会影响任何内容的工作方式。如果无效的 HTML 出现错误,您可以随时在其中添加一个超级最小的空白 GIF 数据 URL,例如
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" ... />
使用 width
和 height
属性可能也是一个好主意,以保持布局并在图像加载时(如果加载)避免重新流。
在 WordPress 中修改 HTML
但是,您如何更改 WordPress 作为评论线程的一部分输出的 HTML 呢?WordPress 中的评论略有不寻常之处,因为 WordPress 核心为您提供了 HTML,它不像大多数其他 HTML 那样是主题的一部分。
可能,在您的 `comments.php` 文件中,您会看到此函数
<?php wp_list_comments(); ?>
它会输出一堆带有整个评论线程的 <li>
。那里没有太多机会来修改图像的输出。但是,我们可以!我们可以在其中列出一个回调函数
<?php wp_list_comments('callback=csstricks_comment'); ?>
该回调函数是我们可以在 `functions.php` 文件中添加的函数的名称。这是一个函数示例,它必须返回一个 <li>
function csstricks_comment($comment, $args, $depth) {
$GLOBALS['comment'] = $comment; ?>
<li <?php comment_class(); ?>">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" width="50" height="50" class="lazyload-gravatar" alt="User Avatar" data-src="<?php echo get_avatar_url(get_comment_author_email($comment_ID), array("size" => 160)); ?>">
<?php comment_text(); ?>
<?php # phantom </li> ?>
<?php }
这非常简化,但您可以看到我们做了什么。我们将 src
替换为空白 GIF,添加了我们最终将在 JavaScript 中用于延迟加载的 class
名称,向实际的 Gravatar 添加了 data-src
,并且正在使用 width
和 height
属性进行占位。这是我实际的 完整的回调,现在在 CSS-Tricks 上实时运行。
如果我们现在发布它,没有任何 JavaScript 工作,我们仍然会有一个功能完善的评论线程,只是图像永远不会加载。
现在我们准备好延迟加载了
困难的部分已经结束。我们现在已经为执行延迟加载做好了充分的准备。如果我们要 编写脚本,它将类似于
- 确定浏览器窗口的可见区域
- 确定页面上每个具有类
.lazyload-gravatar
的图像的位置 - 如果这些图像中的任何一个位于可见区域内,则使用
data-src
中的值替换src
- 如果浏览器窗口的可见区域以任何方式发生变化,请重新评估上述操作
我们可以着手自己编写它。我们也可以做到!但是,我相信您对此并不感到意外,它有点棘手和细致。跨浏览器问题、性能问题、是否在移动设备上工作的问题,仅举几例。对于这类事情,我乐于依赖他人的工作,而不是自己动手。
同样,不出所料,有大量选项可供选择。就我而言,我在 CSS-Tricks 上很乐意使用 jQuery,并且我选择了一个基于 jQuery 的选项,我认为它看起来不错

API 尽可能简单。在将库与我正在使用的其他库捆绑在一起后,我只是调用
$('.lazyload-gravatar').Lazy();
看看它运行得多么完美!
这节省了大量的 HTTP 请求,并且对性能非常有利。
这让你希望 Web 标准和浏览器能够走到一起,并将其作为一项原生功能。
不错的文章——Gravatar 绝对是延迟加载的良好候选对象,因为某些用户可能根本不会看到它们,从而节省大量加载时间和数据。
我建议的一件事是,不要完全删除 src,而是用占位符替换它,例如这个—— http://www.dfhtechnologies.com/images/user.png
这样,您仍然可以发送有效的 HTML,如果脚本出现问题,至少仍然可以看到某些内容,并且您仍然可以使用 JavaScript 进行增强。这是双赢的!
他为此使用了数据 URL。它看起来不太漂亮,但如果一切顺利,用户根本不应该看到图像。
它还可以节省一个 HTTP 请求。
我想这取决于个人喜好;)
没错,但我认为我们还应该考虑所有情况不顺利的情况。
缓慢的数据连接、浏览器支持和防火墙都可能阻止 JavaScript 文件顺利下载和运行。
有关更多信息,请参阅 https://kryogenix.org/code/browser/everyonehasjs.html。
通过使用占位符图像而不是空白 gif,即使 JavaScript 失败,页面看起来也完整而不是损坏。
如果节省 HTTP 请求很重要,您也可以将占位符图像转换为数据 URL。
我希望脚本更智能一些。
现在它们以空白滚动并需要半秒钟才能显示。
您能否扩展范围并在它们距离可见区域 20vmax(例如)时获取它们?
您是否看到了在初始化插件时可以设置的
threshold
选项?设置如下内容应该可以解决问题。注意:这尚未经过测试
好文章!延迟加载在这种情况下效果非常好,而且出奇地简单。
我同意 Adam Taylor 的观点,使用占位符可以让您输出有效的 HTML,并且看起来比使用空白 GIF 更好。
关于原因和可能存在的问题的精彩文章。
我从 tweakers.net(荷兰网站)的一位开发人员那里学到了一些建议,我很乐意分享这些建议,这些建议可以解决一些问题。
除了gif(Adam 的建议也很好),你还可以使用 data:svg。你可以给它实际的图像尺寸。
其次,对于非 js 用户,你可以使用 noscript 标签传递图像的真实版本。你只需要一个非常基本的检查,如果 JS 已开启,就开始显示不在 noscript 标签中的图像版本。
$tmpSrc = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'"
. " width='{$width}' height='{$height}'/%3E";
<noscript>
<img width='<?=$width?>' height='<?=$height?>' alt="<?=$alt?>" src="<?=$src?>">
</noscript>
<img width='<?=$width?>' height='<?=$height?>' alt="<?=$alt?>" src="<?=$tmpSrc?>" data-aym-lazy="<?=$src?>">
以及 css
.no-js noscript + img {
display: none;
}
变量 $width 和 $height 等都来自另一段代码,该代码尽力从任何图像(甚至 svg)中找到这些值。
希望我可以在自己未经审核的评论上发表评论。
我并没有真正说明为什么要拥有实际的图像尺寸。这在需要图像在浏览器中自适应的地方特别有用。
例如,一个宽度为 2000px,高度为 500px 的图像。
通常在你的 css 中你会声明类似这样的内容
img {
width: 100%;
}
height: auto;
如果我们在一个 1000px 宽的窗口中使用临时图像,会发生什么情况?
<img src='tmpimage1pxsquare.gif' width=2000 height=500 lazy-src='actualimage.jpg'>
给定的 width 和 height 属性不起作用,因为它们被 css 覆盖了。
对我来说是新的领域。有趣。但我没有在这个页面上看到任何头像(使用 Firefox 52.0.2)——我的 Firefox 是您认为仅仅是装饰的浏览器吗,还是这是一个错误?
检查你的拦截插件。有些会拦截头像。
:翻白眼表情