延迟加载图像的源占位符

Source placeholder for lazy loading images

我正在使用延迟加载机制,该机制仅在相关图像出现在用户视口中时才加载它们。

为此,我定义了一个 data-src 属性,它链接到原始图像和一个 base64 编码的占位符图像作为 src 属性,以使 HTML 有效。

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-src="/path/to/image.png" alt="some text">

我注意到 chrome 缓存了 base64 字符串,但该字符串很长并且使我的 HTML 膨胀(我的页面上有很多图像)。

所以我的问题是使用小的 base64 编码图像还是 1px x 1px 占位符图像更好?

注意: 出于 SEO 目的,该元素必须是 img。此外,我的 HTML 必须有效,因此需要 src 属性。

我会根据你的情况使用占位符。

使用 base64 编码的图像有点违背了延迟加载的目的,因为您仍然需要向浏览器发送一些图像数据。如果有的话,这可能会对性能产生不利影响,因为图像是作为原始 HTTP 请求的一部分下载的,而不是像浏览器那样通过单独的请求使用图像标记和 URL.

理想情况下,如果它只是一个 'loading' 占位符或类似的东西,我会在 CSS 中创建它,然后在用户充分向下滚动以调用加载时用加载的图像替换它那张特定的图片。

您可以在 src 标签(1x1 像素 GIF)中使用这张较短(但有效!)的图片:

data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=

请注意,如果您对 HTML 进行 gzip(您应该这样做),则字符串的长度不会那么重要,因为重复的字符串压缩得很好。

根据您的需要,您可能希望为 1x1 像素使用一种颜色(生成更短的 gif 文件)。一种方法是使用 Photoshop 或类似工具创建颜色正确的 1x1 像素 GIF,然后使用 ImageOptim 等工具找到最佳压缩率。有多种在线工具可将生成的文件转换为数据 URL.

I noticed that chrome caches the base64 string but the string is quite long and bloats my HTML (I have a lot of images on a page).

如果是这种情况,请考虑放置一个 'real' src 属性指向始终相同的占位符。您确实需要一个额外的 HTTP 请求,但是:

  1. 它几乎可以肯定是流水线式的并且花费的时间很少。
  2. 它会触发图片缓存机制,而base64不会这样做,这样图片实际上只会被解码一次。考虑到今天的 CPU 和 GPU,这不是什么大问题,但无论如何。
  3. 它也将作为资源缓存,并且使用正确的 headers,它将保持 时间,在所有后续页面点击中给出零加载时间来自同一个客户。

如果页面上的图片数量很多,使用 "real" 图片可能会更好。

我敢打赌它会与浏览器、蜘蛛程序等更加兼容 -- 广泛支持 base64 编码,但纯图像更是如此。

甚至比the smallest images you can get in base64, 26 bytes become this

src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="

你可以从

src="/img/p.png"

一直到

src="p.png"

这看起来很简单——如果这样的词存在的话。

测试

我有运行一个非常基本的测试

<html>
<body>
<?php
    switch($_GET['t']) {
        case 'base64':
            $src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';

            break;
        case 'gif':
            $src = 'p.gif';
            break;
    }
    print str_repeat("<img src=\"{$src}\"/>", $_GET['n']);
?>
</body>
</html>

我得到了:

images   mode      DOMContentLoaded   Load      Result
200      base64    202ms              310ms     base64 is best
200      gif       348ms              437ms
1000     base64    559ms              622ms     base64 is best
1000     gif       513ms              632ms
2000     base64    986ms             1033ms     gif is best
2000     gif       811ms              947ms

所以,至少在我的机器上,我似乎给了你一个错误的建议,因为你看不到页面加载时间的优势,直到你几乎 两千张图片。

但是:

  • 这在很大程度上取决于服务器和网络设置,甚至更多取决于实际 DOM 布局。
  • 我每组只 运行 一个测试,这是糟糕的统计,使用 Firebug,这是糟糕的方法 - 如果你想要可靠的数据,运行 几十个使用某些 Web 性能监控工具和真实页面的克隆以任一模式加载页面。
  • (使用 PNG 而不是 gif 怎么样?)

对于 响应式 图像占位符,我使用内联 SVG 取得了不错的效果,如 here 所述。

基本上,您可以输入类似

的内容
data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 500 500'%3e%3c/svg%3e

在您的 <img>src 属性中。注意保持 viewBox 值纵横比与真实图像尺寸一致。这样你的布局就不会跳来跳去导致不必要的重绘。