图片过大是 WordPress 网站加载慢的最常见原因之一。通过将 JPG、PNG 转换为 WebP 或 AVIF 格式,通常可以减少 30%–70% 的图片体积,从而显著提升页面加载速度、改善 Core Web Vitals 评分,并降低用户跳出率。
本文以 Converter for Media(原 WebP Converter for Media)为例,讲解如何在 Nginx 服务器环境下完成 WordPress 图片压缩与格式转换,并正确配合 Cloudflare 缓存,避免“图片格式错乱”或“插件检测不通过”的问题。
如果你使用 WP Panel 管理站点,文中会说明在哪一层面板入口写入 Nginx 规则。
参考文档:
- Configuration for Nginx server
- Configure Cloudflare Caching to use with the Converter for Media plugin
- Cloudflare Vary for Images
一、为什么要做 WordPress 图片压缩与格式转换?
- WebP 比 JPEG 小约 25%–35%,AVIF 甚至比 WebP 再小 20%–50%。
- 图片体积下降直接影响 LCP(最大内容绘制),是 Google Core Web Vitals 的重要指标。
- 加载速度越快,用户体验越好,SEO 排名和转化率也越容易提升。
- 使用 Converter for Media 这类插件,可以在不修改图片 URL 的情况下,自动根据浏览器支持返回 WebP 或 AVIF,兼容旧浏览器。
二、Nginx 环境下需要手动添加什么规则?
Apache 服务器通常可以通过 .htaccess 自动生效,但 Nginx 不支持 .htaccess,当你启用插件后,插件界面会提示:
服务器配置错误
对于Nginx服务器,请联系您的主机技术支持,以使插件正常运行。您的服务器需要额外的配置,但您的主机技术支持将为您处理。
因此,我们需要手动去给服务器添加Nginx配置才能让插件正常工作。
2.1 在 WP Panel 中写入 Nginx 规则
登录 WP Panel 后,按以下路径进入:
网站管理 -> 网站详情 -> Nginx 自定义配置 -> Server 级配置
将下方的官方规则粘贴进去:
# BEGIN Converter for Media
set $ext_avif ".avif";
if ($http_accept !~* "image/avif") {
set $ext_avif "";
}
set $ext_webp ".webp";
if ($http_accept !~* "image/webp") {
set $ext_webp "";
}
location ~* ^/wp-content/(?<path>.+)\.(?<ext>jpe?g|png|gif|webp)$ {
add_header Vary Accept;
add_header Cache-Control "private";
expires 365d;
try_files
/wp-content/uploads-webpc/$path.$ext$ext_avif
/wp-content/uploads-webpc/$path.$ext$ext_webp
$uri =404;
}
# END Converter for Media
保存后,WP Panel 会自动执行 Nginx 语法检查。配置合法才会真正生效,面板会阻止错误的配置写入,避免 Nginx 损坏。
宝塔面板用户?参考:宝塔面板修改nginx配置支持Converter for Media插件
2.2 为什么必须放在 Server 级配置?
Converter for Media 的规则需要插入到当前站点的 server { ... } 块中,并且要早于其他图片静态资源 location。WP Panel 的 Server 级配置正好会被插入到站点 Nginx 配置的靠前位置,适合放这类插件规则。
三、插件提示“HTTP 请求被缓存”是什么意思?

规则已经添加,但插件后台仍可能提示:
您的服务器似乎使用缓存进行 HTTP 请求。不是每次加载图像时都会执行来自
.htaccess文件或 Nginx 配置的规则,而是执行来自缓存的最后一次重定向。
这通常不是 Nginx 规则写错,而是 CDN 或缓存层没有正确处理这两个响应头:
Vary: Accept
Cache-Control: private
Converter for Media 会根据浏览器请求头里的 Accept 判断返回 WebP 还是 AVIF。同一个 JPG/PNG URL,支持的浏览器可能拿到 WebP/AVIF,不支持的浏览器则拿到原图。如果 CDN 只按 URL 缓存、不按 Accept 区分,就会出现:
- 支持 WebP 的浏览器拿到 JPG;
- 不支持 WebP 的浏览器拿到 WebP;
- 插件一直提示缓存异常;
- Cloudflare 响应头显示
CF-Cache-Status: HIT,但请求根本没有回到源站 Nginx。
四、Cloudflare 免费版如何处理?
要让 CDN 正确缓存这种“同一 URL 不同格式”的动态图片响应,CDN 必须支持按 Accept 头区分缓存。Cloudflare 的这项能力叫做 Vary for Images。
根据 Cloudflare 官方文档,Vary for Images 仅支持 Pro、Business、Enterprise 套餐,免费版不支持。
因此:
- Cloudflare Free 用户:不建议缓存
/wp-content/uploads/*下的转换图片,应让请求回源,由 Nginx 按Accept返回正确格式。 - Cloudflare Pro / Business / Enterprise 用户:可以按照 Converter for Media 官方文档配置 Cloudflare API Token 和 Zone ID,让插件自动完成 Cloudflare 图片缓存配置。
- 如果 Free 套餐强行缓存图片,可能导致插件提示 HTTP 请求缓存异常,或者不同浏览器拿到不匹配的图片格式。
换句话说,Cloudflare 免费版不是“不需要配置”,而是“不支持按 Accept 区分图片缓存的能力”。免费版用户如果想保证插件检测通过和图片格式兼容,应该绕过这类动态图片缓存。
但是问题来了,如果缓存规则配置绕过了uploads目录下的资源缓存,网站最大的流量消耗资源不就没走CDN了吗?所以,我们可以换另外一种形式来实现网页图片依然走CDN流量。
五、Cloudflare免费版与 Converter for Media 兼容处理
第四点已经说了,因为免费版的Cloudflare不支持自动按 Accept 头区分图片缓存,所以就算你用插件把所有图片都转换为了webp格式,但是在CDN请求时默认忽略你服务器的图片自动判断规则,默认直接走原图,不会管你是否存在webp。
这个时候我们可以借助HTML5 的< picture >标签来实现图片输出webp和原图两种格式。
将下面的代码复制粘贴到你网站主题函数文件functions.php里面。
/**
* WordPress + Cloudflare Free + Converter for Media
* 仅在 WebP 文件真实存在时,将 jpg/png 图片包装为 picture。
* 支持 uploads 目录 + 当前主题目录图片。
*/
function nbj_get_webp_info($src, $uploads) {
$src_raw = html_entity_decode($src);
$src_path = parse_url(esc_url_raw($src_raw), PHP_URL_PATH);
if (!$src_path || strpos($src_path, '..') !== false) {
return false;
}
/**
* 1. 处理媒体库 uploads 图片
*/
$uploads_baseurl = $uploads['baseurl'];
$uploads_basedir = $uploads['basedir'];
$uploads_base_path = parse_url(esc_url_raw($uploads_baseurl), PHP_URL_PATH);
if ($uploads_base_path && strpos($src_path, $uploads_base_path . '/') === 0) {
$relative = ltrim(substr($src_path, strlen($uploads_base_path)), '/');
if (!$relative) {
return false;
}
$webp_url = str_replace('/wp-content/uploads/', '/wp-content/uploads-webpc/uploads/', $src_raw) . '.webp';
$webp_path = dirname($uploads_basedir) . '/uploads-webpc/uploads/' . $relative . '.webp';
return [
'url' => $webp_url,
'path' => $webp_path,
];
}
/**
* 2. 处理当前主题目录图片
* 规则:/wp-content/themes/your-theme/xxx.jpg
* 对应:/wp-content/themes/your-theme/xxx.jpg.webp
*/
$theme_baseurl = get_stylesheet_directory_uri();
$theme_basedir = get_stylesheet_directory();
$theme_base_path = parse_url(esc_url_raw($theme_baseurl), PHP_URL_PATH);
if ($theme_base_path && strpos($src_path, $theme_base_path . '/') === 0) {
$relative = ltrim(substr($src_path, strlen($theme_base_path)), '/');
if (!$relative) {
return false;
}
$webp_url = $src_raw . '.webp';
$webp_path = rtrim($theme_basedir, '/') . '/' . $relative . '.webp';
return [
'url' => $webp_url,
'path' => $webp_path,
];
}
return false;
}
function nbj_wrap_webp_picture($content) {
if (is_admin() || is_feed() || (defined('REST_REQUEST') && REST_REQUEST)) {
return $content;
}
if (stripos($content, '<img') === false) {
return $content;
}
$uploads = wp_upload_dir();
// 支持 jpg/png,以及 jpg/png 后面带 query string 的情况
$pattern = '/<img\b[^>]*\bsrc=(["\'])([^"\']+\.(?:jpe?g|png)(?:\?[^"\']*)?)\1[^>]*>/i';
return preg_replace_callback($pattern, function ($m) use ($uploads) {
$img_tag = $m[0];
$src = html_entity_decode($m[2]);
if (
strpos($img_tag, 'data-nbj-webp') !== false ||
strpos($src, 'uploads-webpc') !== false ||
strpos($src, '.webp') !== false
) {
return $img_tag;
}
$webp = nbj_get_webp_info($src, $uploads);
if (!$webp || !is_file($webp['path'])) {
return $img_tag;
}
$img_tag = preg_replace('/<img\b/i', '<img data-nbj-webp="1"', $img_tag, 1);
return '<picture data-nbj-webp="1">'
. '<source srcset="' . esc_url($webp['url']) . '" type="image/webp">'
. $img_tag
. '</picture>';
}, $content);
}
add_filter('the_content', 'nbj_wrap_webp_picture', 999);
add_filter('widget_text_content', 'nbj_wrap_webp_picture', 999);
add_action('template_redirect', function () {
if (
!is_admin()
&& !is_feed()
&& !(defined('REST_REQUEST') && REST_REQUEST)
&& ob_get_level() === 0
) {
ob_start('nbj_wrap_webp_picture');
}
});
添加这个代码后,WordPress在前台输出内容时,就会先做一个判断,将你uploads目录下的图片文件全部添加<picture>标签。

当支持Webp格式的浏览器(2026年基本上很难碰到不支持的设备了)默认会读取第一个source里面的webp格式图片,如果这个图片不存在或者还没转换完成,会降级读取下面的png原图(不支持webp格式的设备会直接读取原图,忽略webp)

所以,现在哪怕你是免费CloudFlare的用户,也可以让浏览器支持webp图片显示且图片走CDN流量了。
六、最终建议:WordPress 图片压缩提速的正确姿势
对于大多数使用 Cloudflare Free 的 WordPress 站长,推荐流程如下:
- 安装并启用 Converter for Media 插件。
- 在 WP Panel 的 Server 级 Nginx 自定义配置中添加官方规则。
- 主题后台函数文件增加HTML5的<picture> 标签代码。
- 清理一次网站和CDN的缓存,让资源刷新。
简单总结:
源站 Nginx 负责图片格式转换;Cloudflare 负责全球加速。
按上述方式配置后,你的 WordPress 站点就能在兼容旧浏览器的前提下,充分发挥 WebP/AVIF 的压缩优势,实现稳定、可持续的图片加载提速。
为什么我划掉了AVIF?因为这个格式转换比较费服务器资源,通常都是调用第三方的转换服务,是要付费项目,通常情况下Webp + CDN已经有不错的提速了。