搜索全站
性能优化 12 分钟阅读

WordPress 接入 CDN 回源配置与缓存规则完整指南

CDN 接上了但命中率只有 20%?多半是缓存规则没配对。本文讲清动静分离、缓存键设计、忽略 query 参数、Cookie 透传等核心设置,并给出国内主流 CDN 的具体配置示例。

U
UFO_PF 2017-11-26 · 阅读 12 分钟
Wo 性能优化
阅读提示
本文约 4,716 字,预计阅读 12 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:接了 CDN,为什么还是慢

很多站长以为在 CDN 控制台填上源站 IP 就完事了,结果发现:

  • CDN 后台显示缓存命中率 15%–30%,大部分请求还是回源;
  • 图片加载快了,HTML 页面一点没快;
  • 登录后状态混乱,一会儿登录一会儿未登录;
  • 改了文章,前台还是旧内容,要等很久才更新。

根本原因:CDN 默认只缓存静态文件,而 WordPress 是动态程序,HTML 默认不缓存。想让 CDN 真正起作用,必须自己设计缓存规则。

原理分析:CDN 缓存的三个决定因素

CDN 节点收到请求后,按以下顺序判断:

  1. 文件类型(后缀):在不在缓存列表里。默认一般是 jpg/png/css/js/woff 等;
  2. 缓存键(Cache Key):用什么字符串标识这个资源。默认通常是 完整 URL(含 query 参数);
  3. 缓存过期时间:来源优先级是「CDN 控制台配置 > 源站的 Cache-Control 头 > CDN 默认策略」。

命中率低的三大杀手:

  • HTML 没配缓存,全部回源;
  • 缓存键包含无关参数,比如 ?utm_source=weibo 每次不同,同一个页面生成 N 份缓存;
  • 源站返回了 Set-Cookie 或 Cache-Control: private,CDN 直接放弃缓存。

保姆级实操

第一步:源站先做好动静分离

把静态资源用独立路径或独立域名,方便 CDN 精准匹配:

# 静态资源加长缓存,并去掉 Cookie
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp|avif|woff|woff2|ttf|eot)$ {
    expires 365d;
    add_header Cache-Control "public, max-age=31536000, immutable";
    add_header Access-Control-Allow-Origin "*";
    access_log off;
    # 关键:静态资源不要带 Cookie,否则 CDN 不缓存
    fastcgi_hide_header Set-Cookie;
}

# wp-content/uploads 下的图片
location ^~ /wp-content/uploads/ {
    expires 365d;
    add_header Cache-Control "public, max-age=31536000";
    access_log off;
    try_files $uri =404;
}

immutable 告诉浏览器和 CDN「这个文件永不改变」,浏览器连 304 校验请求都不发了。前提是文件名带版本号——WordPress 的 CSS/JS 本来就带 ?ver=6.5.2,没问题。

第二步:分离动静域名(可选但推荐)

在 wp-config.php 里指定 uploads 的 URL:

define( 'WP_HOME',    'https://mimangfei.com' );
define( 'WP_SITEURL', 'https://mimangfei.com' );
// 媒体库走独立域名
define( 'UPLOADS', '' ); // 保持默认目录

更简单的方式是用 wp_upload_dir 过滤器改 URL:

add_filter( 'upload_dir', function( $uploads ) {
    $uploads['url']     = str_replace( 'https://mimangfei.com', 'https://static.mimangfei.com', $uploads['url'] );
    $uploads['baseurl'] = str_replace( 'https://mimangfei.com', 'https://static.mimangfei.com', $uploads['baseurl'] );
    return $uploads;
} );

注意:老文章的硬编码图片 URL 不会自动变,需要用 WP-CLI search-replace 批量替换域名 处理一遍数据库。

第三步:CDN 控制台缓存规则配置

以国内主流 CDN(阿里云 / 腾讯云 / 又拍云)为例,规则逻辑基本一致:

路径规则 缓存时间 忽略参数 说明
*.php 0 秒(不缓存) — 动态脚本
/wp-admin/* 不缓存 — 后台
/wp-login.php 不缓存 — 登录页
/wp-json/* 0–60 秒 否 REST API,按需
/wp-content/* 30 天 是 插件主题静态资源
/wp-includes/* 30 天 是 核心静态资源
*.html 不缓存 或 5 分钟 是 静态化站点可缓存
/(首页) 5–30 分钟 是 内容站可开
/*(默认) 不缓存 — 兜底

“忽略参数”(过滤参数 / 忽略 query string)这一项必须打开,否则 ?utm_source=、?from= 之类的推广参数会让同一个页面产生无数份缓存,命中率直接崩盘。

第四步:设置缓存键(Cache Key)

如果 CDN 支持自定义缓存键,尽量简化为:

$scheme$host$uri          # 不含 query 参数

如果你开了移动端适配(同一 URL 返回不同 HTML),必须加设备维度:

$scheme$host$uri$is_mobile

对应的源站要在 Nginx 里输出 Vary: User-Agent 或 Vary: Cookie。

第五步:HTML 到底缓不缓存

分三种情况:

  1. 纯内容站(博客、文档):可以缓存。在 CDN 后台把 / 和 /category/*、/tag/* 设为 5–30 分钟,并在 Cookie 判断里排除 wordpress_logged_in。国内 CDN 一般有”过滤 Cookie”开关,打开后 Set-Cookie 不会被写入缓存。
  2. 有登录/会员的站:HTML 不缓存,只缓存静态资源。
  3. 电商站(WooCommerce):HTML 不缓存,且必须排除 woocommerce_items_in_cart、wp_woocommerce_session 这两个 cookie,否则购物车串号。

第六步:配置回源 Host

这是最容易填错的一项。回源 Host 必须填你的站点域名,不是源站 IP。因为一台服务器上可能跑着十几个站点,Nginx 靠 Host 头决定用哪个 server 块。填成 IP 会返回默认站点的内容,表现为”CDN 节点访问正常,线上访问是别的网站”。

回源地址:1.2.3.4(源站 IP)或 origin.mimangfei.com
回源 Host:mimangfei.com        ← 关键
回源协议:HTTPS(如果源站有证书)
回源端口:443

第七步:配置缓存刷新

WordPress 发文章后要主动刷新 CDN。在主题的 functions.php 或做个小插件:

/**
 * 发布/更新文章时刷新 CDN 对应 URL
 */
function mmf_purge_cdn_on_save( $post_id, $post ) {
    if ( wp_is_post_revision( $post_id ) || 'publish' !== $post->post_status ) {
        return;
    }
    $urls = array(
        home_url( '/' ),
        get_permalink( $post_id ),
    );
    // 文章所属分类页
    $cats = wp_get_post_categories( $post_id );
    foreach ( $cats as $cid ) {
        $urls[] = get_category_link( $cid );
    }
    // 阿里云 CDN 刷新 API 示例(需自己补全签名逻辑)
    wp_remote_post( 'https://cdn.aliyuncs.com/', array(
        'timeout' => 5,
        'body'    => array(
            'Action'      => 'RefreshObjectCaches',
            'ObjectType'  => 'File',
            'ObjectPath'  => implode( "\n", $urls ),
        ),
    ) );
}
add_action( 'save_post', 'mmf_purge_cdn_on_save', 10, 2 );

实际生产环境建议直接用对应厂商的 SDK 或现成插件(如 CDN Enabler),上面的代码是说明原理。

常见踩坑

  1. 缓存命中率上不去:先查是不是没开”忽略参数”,再看源站有没有输出 Set-Cookie。用 curl -I 看源站响应头。
  2. HTTPS 配置导致重定向循环:源站没配 SSL,CDN 回源用 HTTP,WordPress 强制 HTTPS → 循环。解决:CDN 回源协议设为 HTTP,同时源站要能识别 X-Forwarded-Proto(见反向代理下 WordPress 取不到真实 IP)。
  3. 刷新了 CDN 但前台还是旧的:浏览器本地缓存没清。硬刷新(Ctrl+F5)或让源站给 HTML 加 Cache-Control: no-cache, must-revalidate(HTML 不走强缓存,但 CDN 仍可缓存)。
  4. 流量账单暴涨:回源率高 + CDN 按请求数计费。重点是提高命中率,其次给图片开 WebP 和压缩。
  5. 案例:某站把 /* 全设为缓存 7 天,结果用户登录后看到的还是游客页面,评论区永远显示”未登录”。排查发现是没排除 wordpress_logged_in cookie。改为只对静态路径缓存后解决。
  6. 图片被 CDN 缓存了旧版本:换了同名图片(文件名没变),CDN 和浏览器都拿旧的。改图时要换文件名或改 ?ver= 版本号。

总结

CDN 配置的核心就三件事:动静分离(静态资源走长缓存 + 去 Cookie)、忽略 query 参数(否则命中率崩)、回源 Host 填域名。HTML 缓存要慎之又慎,有登录态的站一律不缓存 HTML,只缓存静态资源。上线后用 curl -I 看 X-Cache / Age 头判断是否命中,再用 GTmetrix 或站长工具测全国访问速度。关于图片本身的体积优化,可以接着看WordPress 图片优化与 WebP 转换。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。