
[2022] Hexo 图片 lazyload 的更优尝试
使用过 Medium 的同学都或许会惊叹于 Medium 流畅的图片懒加载体验。于是我就想,能否在我的 Hexo 博客中也达到这样的一个 lazyload 效果呢?在参考了不少资料(特别是前辈产出的博文)后,我得到一个还令我满意的 Hexo 图片懒加载尝试。
时隔多日的更新:此时距离我重新部署 lazyload 已经过去了有一阵子了,从谷歌统计数据看来,我的网站 DOMContentLoaded
提升近 1s 。懒加载带来如此明显的性能提升还是有点超出我的预料,前端性能方面也确实值得我们重视。
核心:srcset 参数
如果在搜索引擎中输入「hexo
+ lazyload
」,出来的多半是让你下载形形色色的插件、甚至叫你引入一些奇奇怪怪的第三方库之类的教程。
这时许多教程都指向一个插件——Hexo lazyload image,当然还是要承认这是一个非常优秀的插件。但是仔细翻阅源代码后发现,Hexo lazyload image 使用的是性能耗费巨大的 scroll 而非我认为比较合适的 IntersectionObserver 实现。
是否真的值得为了那不到 7% 的 IE 用户做出如此大的牺牲呢?更何况这种实现方案在 RSS 等爬取工具中就只能得到一个 lazyload.png
,还是十分影响体验的。

不过好在也有人分享了一种更加现代的实现方案,不仅能充分发挥现代浏览器的优势,还能在老旧设备和 RSS 等工具中不进行 lazyload 、直接加载原图。
这里就用到了 srcset
这个关键字,srcset
和 src
属性一样,可是优先级更高。
<img src="origin.png"
srcset="thumbnail.png"
data-srcset="origin.png">
这样,即便我们不对 src
动刀,现代浏览器还是会先加载放在 srcset
中的缩略图 thumbnail.png
,比如我就放了一个 1x1 的 base64 小图。而利用 lazyload JS 监控元素可视情况,当图片出现在可视范围内时候就将 data-srcset
赋给 srcset
显示原图 origin.png
。而在不兼容 srcset
的历史浏览器中和 RSS 等工具中,直接加载 src
属性显示原图,从而避免放着张 lazyload.png
在 RSS 阅读器里的尴尬。
你可以 点击这里 查看浏览器关于 srcset
的兼容情况。
细节:渐入加载与布局抖动
简单粗暴的塞入图片往往导致突兀的体验,这其中还有些许细节值得留意。
渐入加载
Medium 加载原图的时候还有一个细节,那就是让图片有一个模糊变清晰的展现效果。个人感觉这样比把 lazyload.png
突兀地换成原图要自然一点。
实现也很简单,只需要添加几个 CSS:
img.lazyload {
transition: filter 0.375s ease 0s;
}
img.lazyload:not(.loaded) {
-webkit-filter: blur(8px);
filter: blur(8px);
}
我在懒加载的图片中添加了 class="lazyload"
然后在原图加载完毕时追加成 class="lazyload loaded"
,代码实现会在下一节放上参考。
布局抖动
图片 lazyload 还带来的一个问题就是布局抖动。由于一开始浏览器根本没有加载原图,也不会给图片自动留好一个位置。所以在加载原图的时候势必会导致窗口布局的抖动。
<img src=”https://blog.ichr.me/images/blog-assets/20200316175531.gif“ blurhash=”LAR