本文约 3,554 字,预计阅读 9 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:为了提速装的插件,可能正是拖慢首屏的原因
「给站点加个懒加载」几乎成了性能优化的标配动作。但不少人在装完懒加载插件后发现,PageSpeed Insights 分数没涨反跌,还多了一条刺眼的提示:Largest Contentful Paint 图片被延迟加载了。原因是,很多懒加载插件的工作方式是「把 src 换成占位符,滚动到视口附近再用 JS 写回真实地址」。对首屏那张最大的图来说,这套流程意味着浏览器必须先下载并执行 JS,才知道要去下载图片——白白多了一个往返。
而原生的 loading="lazy" 完全不是这个逻辑。它由浏览器在布局阶段直接决策,不依赖任何脚本,首屏之外的图片会被推迟,首屏之内的图片正常加载。WordPress 从 5.5 起已经默认给内容里的图片加上这个属性,换句话说,大多数站点根本不需要再装懒加载插件。
原理分析:两种实现路径的差异
WordPress 5.5 引入的懒加载发生在内容输出阶段:wp_filter_content_tags() 会遍历正文里的 img 标签,通过 wp_img_tag_add_loading_attr() 为其添加 loading="lazy",同时加上 decoding="async" 提升解码效率。整个过程在服务端完成,输出的 HTML 里就已经带上了属性,浏览器拿到即可生效。
| 维度 | 原生 loading="lazy" |
JS 懒加载插件 |
|---|---|---|
| 触发方式 | 浏览器原生调度 | 监听滚动 + JS 改写 src |
| 是否依赖 JS | 否 | 是,脚本失败则图片不显示 |
| 首屏风险 | 由开发者控制排除 | 容易把首屏图一并延迟 |
| 爬虫可见性 | HTML 里有真实 src | 只有 data-src,需 noscript 兜底 |
| 额外开销 | 近乎为零 | 需加载一个 JS 文件 |
关键点在于:原生方案是「默认全部懒加载,需要你主动排除首屏」。WordPress 并没有智能到能判断哪张图在首屏,它会给所有正文图片都加上 loading="lazy",包括第一张。因此使用原生方案时,你的核心工作从「装插件」变成了「把首屏图排除掉」。
具体钩子有三个,作用各不相同:wp_lazy_loading_enabled 控制某个标签是否启用懒加载(默认针对 img、iframe),wp_img_tag_add_loading_attr 可以修改最终写入的属性值,wp_get_attachment_image_attributes 则用于在输出附件图片时直接指定属性。
保姆级实操:把懒加载交给浏览器
步骤1:确认站点当前是谁在做懒加载。 打开前台页面源码,搜索 loading= 和 data-src。如果同时看到两者,说明原生和插件在重复工作,先关掉插件的懒加载功能(很多插件的设置页里就叫「Lazy Load」或「延期加载图片」)。
步骤2:全局梳理,只保留一种方案。 若主题或某些插件强制注入 JS 懒加载,可以在主题里直接关掉原生方案做对照测试,但更推荐的做法是反过来——保留原生,停用插件。
<?php
// 极端情况下才用:彻底关闭 WordPress 原生懒加载
add_filter( 'wp_lazy_loading_enabled', '__return_false' );
步骤3:让首屏图片立即加载。 这一步是提升 LCP 的关键。对特色图、首屏 banner,显式声明 loading="eager" 与 fetchpriority="high",让浏览器把它排进最高优先级。
<?php
// 主题模板中输出特色图时指定加载属性
echo wp_get_attachment_image( get_post_thumbnail_id(), 'large', false, array(
'loading' => 'eager',
'fetchpriority' => 'high',
'decoding' => 'sync',
) );
步骤4:把正文里的第一张图从懒加载中摘出来。 下面的过滤器只对正文(the_content 上下文)生效,把第一张出现的图片改成立即加载,其余保持懒加载。
<?php
// 正文第一张图不做懒加载,避免 LCP 被推迟
add_filter( 'wp_img_tag_add_loading_attr', function ( $value, $image, $context ) {
static $first_done = false;
if ( 'the_content' === $context && ! $first_done ) {
$first_done = true;
return 'eager';
}
return $value;
}, 10, 3 );
步骤5:处理 iframe 与视频。 嵌入的地图、YouTube 播放器同样会拖慢首屏。原生方案对 iframe 也生效,更好的做法是使用「封面图 + 点击加载」的 facade 方案,把几十 KB 的封面换成几百 KB 的播放器资源。
步骤6:给懒加载图片补齐尺寸属性。 懒加载本身不产生 CLS,但缺 width/height 会。WordPress 通常会自动补上,若用了自定义 HTML 模块,请手动写明,或用 CSS aspect-ratio 占位。
/* 为懒加载图片预留空间,避免布局跳动 */
.entry-content img {
max-width: 100%;
height: auto;
aspect-ratio: attr(width) / attr(height);
}
步骤7:验证结果。 用 Chrome DevTools 的 Network 面板滚动页面,观察图片请求的发起时机;再跑一次 Lighthouse,重点看是否还有「Largest Contentful Paint image was lazily loaded」这条审计项。
常见踩坑
- 首屏图被懒加载是最常见的错误,表现就是 LCP 时间莫名多出几百毫秒。用上面的步骤3、步骤4 处理。
- 两套懒加载叠加。插件把
src换成占位符,原生的loading="lazy"又加在占位图上,结果是图片永远不加载——页面滚动到底还是灰块。 noscript缺失影响收录。JS 方案下爬虫只能看到data-src,Google 图片搜索可能抓不到图。原生方案不存在这个问题,这也是推荐它的重要原因之一。- 页面缓存把改写后的 HTML 缓存死。使用 JS 方案时,如果缓存插件缓存了「尚未加载」状态的 HTML,用户可能拿到不完整的页面。
- 懒加载救不了尺寸问题。一张 2560px 的图即便懒加载,滚动到它时依然要下载完整体积。真正的解法是配合 srcset 输出合适尺寸,这一点在用插件实现图片 CDN 加速与自适应尺寸里有详细说明。
- 案例:某企业站启用某缓存插件自带的懒加载后,首页轮播首图被换成了 1×1 灰色占位 SVG,LCP 从 1.9s 恶化到 4.3s,客户反馈「首页打开一片灰」。排查时先用源码确认存在
data-src,再在插件设置里把「Skip first images」设为 2,最后干脆停用插件懒加载、改用原生属性并把首图设为 eager,LCP 回落到 1.4s。 loading="lazy"在极老的 Safari 上不生效,但会安全降级为立即加载(不会导致图片不显示),这是原生方案相对 JS 方案的又一个优势。- 后台编辑器里的图片也会被加属性。若在后台发现异常,可用
wp_lazy_loading_enabled按上下文判断跳过。
总结
选型结论很明确:能用原生 loading="lazy" 就不要再装 JS 懒加载插件。原生方案零脚本开销、爬虫可见、失败可降级,唯一需要你动手的是「把首屏那几张图摘出来」。行动清单:停用插件懒加载 → 确认源码里只有 loading= 没有 data-src → 首图设 eager + fetchpriority="high" → 补齐宽高 → 用 Lighthouse 复核。做完这五步,懒加载这块基本不会再出问题。若你还想进一步压缩图片体积,可先看ShortPixel/Imagify/Smush 图片压缩插件对比。
