夜雨聆风学习资料网

ARTICLE · 1000621

WordPress 缓存插件装了却没真正生效?实测让 Nginx 直接读取 Cache Enabler 静态缓存,绕过 PHP 和 MySQL

WordPress 缓存插件装了却没真正生效?实测让 Nginx 直接读取 Cache Enabler 静态缓存,绕过 PHP 和 MySQL
最近我重新整理了几个 WordPress 网站的服务器缓存配置。

之前我一直认为:

WordPress 安装了 Cache Enabler,缓存文件正常生成,网站缓存就算完成了。

但这次真正排查以后发现,并不是这么回事。

Cache Enabler 成功生成缓存文件,不等于 Nginx 已经在使用这些缓存文件。

在很多 WordPress 网站上,实际访问链路依然是:

浏览器  ↓Nginx  ↓PHP  ↓WordPress  ↓MySQL  ↓生成 HTML

即使服务器目录里已经存在:

https-index.html.gz

浏览器访问页面时,仍然可能重新启动 PHP、加载 WordPress、加载插件、查询数据库。

这次我分别在两种常用服务器环境下重新做了测试:

宝塔面板 + Nginx + WordPressLNMP + Nginx + WordPress

最终实现:

普通访客  ↓Nginx  ↓Cache Enabler 静态 HTML.gz  ↓直接返回浏览器

也就是说:

普通前台页面不再经过 PHP、WordPress 和 MySQL。

实际测试中,一个已经命中静态缓存的首页请求:

time_total0.026557

大约 26ms。

当然,这个数字不能直接等同于浏览器完整打开网站的速度,因为页面还要加载图片、CSS、JS、字体等资源。

但从服务器处理 HTML 的角度来看:

Nginx 读取一个几十 KB 的静态 gzip 文件,和重新运行一遍 WordPress,完全不是一个级别的开销。

这篇文章把整个配置和排查过程完整整理下来。

一、Cache Enabler 到底缓存了什么?

Cache Enabler 是一个比较轻量的 WordPress 页面缓存插件。

它会把 WordPress 最终生成的 HTML 页面保存为静态文件。

例如首页可能生成:

wp-content/cache/cache-enabler/example.com/https-index.html.gz

产品页面可能生成:

wp-content/cache/cache-enabler/example.com/product/example-product/https-index.html.gz

如果启用了移动端缓存,还可能看到:

https-index-mobile.html.gz

也就是说,第一次访问页面时:

Nginx ↓PHP ↓WordPress ↓MySQL ↓生成 HTML ↓Cache Enabler 保存缓存

理论上,第二次访问就没有必要再运行 WordPress。

理想状态应该是:

Nginx ↓https-index.html.gz ↓浏览器

这才是我们真正想要的静态页面缓存。

二、缓存文件存在,并不代表缓存真的命中了

这是这次排查中最关键的一点。

我首先检查 Cache Enabler 的缓存目录。

宝塔环境通常可以执行:

find /www/wwwroot/example.com/wp-content/cache/cache-enabler \-type f | head -30

LNMP 一般是:

find /home/wwwroot/example.com/wp-content/cache/cache-enabler \-type f | head -30

如果看到:

https-index.html.gz

说明:

Cache Enabler 插件本身已经正常工作。

例如:

/home/wwwroot/example.com/wp-content/cache/cache-enabler/example.com/https-index.html.gz

产品页:

/home/wwwroot/example.com/wp-content/cache/cache-enabler/example.com/product/example-product/https-index.html.gz

到这里,只能证明:

WordPress 成功生成了静态缓存。

但还不能证明:

Nginx 正在直接返回这些文件。

三、怎么判断请求到底有没有经过 PHP?

可以直接使用 curl。

curl -I \-H ”Accept-Encoding: gzip” \https://example.com/

如果返回类似:

HTTP/2 200server: nginxcontent-type: text/html; charset=UTF-8x-powered-by: PHP/8.1link: ; rel=”https://api.w.org/”content-encoding: gzip

这里最值得注意的是:

x-powered-by: PHP/8.1

以及 WordPress 返回的:

wp-json

这说明:

当前请求仍然进入了 PHP 和 WordPress。

即使缓存目录里面已经存在 HTML 缓存,也没有真正实现 Nginx 直读缓存。

四、给 Nginx 增加一个 X-Cache 响应头

为了以后方便判断缓存状态,我直接在 Nginx 的静态缓存 location 中增加:

add_header X-Cache ”Cache-Enabler-HIT” always;

这样以后只需要:

curl -I \-H ”Accept-Encoding: gzip” \https://example.com/

看到:

x-cache: Cache-Enabler-HIT

同时:

x-powered-by: PHP

消失,就可以比较明确地判断:

Nginx 已经直接返回 Cache Enabler 的静态页面。

实际成功后的响应大概是:

HTTP/2 200server: nginxcontent-type: text/htmlcontent-length: 26393last-modified: Wed, 02 Sep 2026 05:19:13 GMTcontent-encoding: gzipvary: Accept-Encodingx-cache: Cache-Enabler-HITaccept-ranges: bytes

这里最关键的是:

x-cache: Cache-Enabler-HIT

以及没有:

x-powered-by: PHP

五、为什么之前 Nginx 可能一直命不中?

我之前排查过一个比较典型的问题。

很多网上的 Cache Enabler Nginx 配置会寻找:

index.html

但我实际服务器生成的是:

https-index.html.gz

甚至有些环境会生成:

https-index-webp.html.gz

移动端则可能是:

https-index-mobile.html.gz

如果你的 Nginx 写的是:

try_files /wp-content/cache/cache-enabler/${host}${uri}/index.html ...

但实际文件是:

https-index.html.gz

那么它永远不会命中。

所以我的原则是:

不要先复制网上的 Nginx 配置。

第一步先执行:

find /网站根目录/wp-content/cache/cache-enabler \-type f | head -30

看看你的 Cache Enabler 到底生成了什么文件。

再根据真实文件名写 Nginx。

六、最终实现的缓存逻辑

我的思路比较简单。

普通访客满足下面条件时尝试缓存:

GET / HEAD 请求没有 URL 参数没有登录 Cookie没有 WooCommerce Session不是后台不是 wp-json不是购物车不是 Checkout浏览器支持 gzip

然后:

请求 ↓判断能否缓存 ↓尝试读取 Cache Enabler 文件 ↓存在 ├─ 是 → Nginx 直接返回 └─ 否 → WordPress

也就是两条线路。

第一条:

Cache HITNginx ↓Cache Enabler ↓HTML.gz ↓Browser

第二条:

Cache MISSNginx ↓PHP ↓WordPress ↓MySQL

七、为什么要绕过登录用户和 WooCommerce?

静态缓存最大的风险,不是“缓存没生效”。

而是:

缓存了本来不应该缓存的页面。

例如 WooCommerce。

如果用户 A 加了一件商品进入购物车:

woocommerce_items_in_cart

如果这时候错误地把页面缓存成公共 HTML:

用户 B 可能看到用户 A 的购物车状态。

所以以下 Cookie 我会直接绕过缓存:

wordpress_logged_inwp-postpasscomment_author_woocommerce_items_in_cartwoocommerce_cart_hashwp_woocommerce_session_

下面这些页面也不进入公共静态缓存:

/wp-admin//wp-login.php/wp-json//xmlrpc.php/wp-cron.php/cart//checkout//my-account/

这一步非常重要。

八、带参数的 URL 我选择直接绕过

例如:

?s=sensor

或者:

?wc-ajax=xxx

以及:

?utm_source=google

从极致性能角度来说,有一些参数其实可以忽略。

例如某些 UTM 参数理论上不会改变页面正文内容。

但我的服务器缓存策略比较保守:

有 query string ↓直接进入 WordPress

也就是:

if ($query_string != ””) {    return 419;}

这样虽然会牺牲少量缓存命中率,但稳定性更高。

对于企业站、SEO 内容站和产品展示站,我认为完全可以接受。

九、宝塔和 LNMP 的主要区别

两种环境的缓存逻辑其实完全一样。

主要区别是目录。

宝塔常见 WordPress 目录:

/www/wwwroot/example.com

LNMP 常见:

/home/wwwroot/example.com

宝塔的网站 Nginx 配置通常可以直接通过:

宝塔→ 网站→ 对应网站→ 设置→ 配置文件

修改。

LNMP 一般位于:

/usr/local/nginx/conf/vhost/

比如:

/usr/local/nginx/conf/vhost/example.com.conf

如果不知道哪个文件是真正生效的,可以:

grep -R -n ”server_name.*example.com” \/usr/local/nginx/conf/vhost /etc/nginx 2>/dev/null

可能会得到:

example.com.confexample.com.conf.bakexample.com.conf.bak-202608

真正需要修改的通常是:

example.com.conf

不要改错备份文件。

十、配置完成后如何测试?

改完 Nginx 后第一件事永远不是 reload。

而是:

nginx -t

LNMP 可以:

/usr/local/nginx/sbin/nginx -t

必须看到:

syntax is oktest is successful

然后才:

/usr/local/nginx/sbin/nginx -s reload

宝塔也可以直接通过面板重载 Nginx。

之后:

curl -I \-H ”Accept-Encoding: gzip” \https://example.com/

成功后的核心标志:

x-cache: Cache-Enabler-HIT

同时:

x-powered-by: PHP

消失。

十一、实际速度测试

我测试使用:

curl -s \-o /dev/null \-w ”time_total: %{time_total}\n” \-H ”Accept-Encoding: gzip” \https://example.com/

返回:

time_total0.026557

大约:

26ms

这只是 HTML 主请求,不代表完整网页只需要 26ms。

但它能够说明一个问题:

服务器已经不再为每个普通访客重新运行 WordPress。

原来的流程:

PHP-FPM ↓WordPress Core ↓Theme ↓Plugins ↓MySQL ↓HTML

现在变成:

Nginx ↓几十 KB gzip 文件

对于内容型 WordPress 网站,这个优化的性价比非常高。

十二、什么网站特别适合这种方式?

我认为比较适合:

企业官网外贸 B2B 网站SEO 内容站产品展示网站Knowledge BaseBlog资讯网站

因为这类网站绝大部分访客只是:

进入页面 ↓阅读内容 ↓离开

没有登录状态,也没有复杂个性化数据。

对于这种请求,每次都重新运行 WordPress,其实没有必要。

十三、需要注意 CDN

如果前面还有 CDN,例如:

Cloudflare ↓Nginx ↓WordPress

这时候需要区分:

CDN HITNginx HITWordPress HIT

我现在增加:

X-Cache: Cache-Enabler-HIT

主要用于确认:

源站 Nginx 是否直接读取了 Cache Enabler。

即使以后再叠加 CDN,也能比较方便地定位问题。

十四、完整配置一:宝塔 + WordPress + Cache Enabler

下面提供一套完整参考配置。

假设:

域名:example.comWordPress:/www/wwwroot/example.comCache Enabler:/www/wwwroot/example.com/wp-content/cache/cache-enabler/

使用之前,请根据自己的服务器调整:

域名网站目录SSL 证书PHP 版本

完整配置:

server{    listen 80;    listen [::]:80;    server_name example.com www.example.com;    root /www/wwwroot/example.com;    location ^~ /.well-known/acme-challenge/    {        allow all;    }    location /    {        return 301 https://example.com$request_uri;    }}server{    listen 443 ssl http2;    listen [::]:443 ssl http2;    server_name example.com www.example.com;    root /www/wwwroot/example.com;    index index.php index.html index.htm;# ================================================================# SSL# ================================================================    ssl_certificate        /www/server/panel/vhost/cert/example.com/fullchain.pem;    ssl_certificate_key        /www/server/panel/vhost/cert/example.com/privkey.pem;    ssl_protocols TLSv1.2 TLSv1.3;    ssl_session_cache shared:SSL:10m;    ssl_session_timeout 10m;# ================================================================# 日志# ================================================================    access_log /www/wwwlogs/example.com.log;    error_log /www/wwwlogs/example.com.error.log;# ================================================================# Cache Enabler# ================================================================    set $ce_device ””;# ------------------------------------------------# Mobile Cache# ------------------------------------------------    if ($http_user_agent ~*        ”(Mobile|Android|Silk/|Kindle|BlackBerry|Opera Mini|Opera Mobi|iPhone|iPod)”)    {        set $ce_device ”-mobile”;    }# ------------------------------------------------# Cache Enabler 文件#    # 首页:#    # wp-content/cache/cache-enabler/# example.com/# https-index.html.gz#    # ------------------------------------------------    set $ce_cache_file        ”/wp-content/cache/cache-enabler/${host}${uri}https-index${ce_device}.html.gz”;# ================================================================# wp-admin 自动补 /# ================================================================    rewrite ^/wp-admin$ $scheme://$host$uripermanent;# ================================================================# WordPress 主入口# ================================================================    location /    {        recursive_error_pages on;        error_page 418 = @cache_enabler;        error_page 419 = @wordpress;# 只处理 GET / HEAD        if ($request_method !~ ”^(GET|HEAD)$”)        {            return 419;        }# 浏览器必须支持 gzip        if ($http_accept_encoding !~* ”gzip”)        {            return 419;        }# 带 URL 参数绕过缓存        if ($query_string != ””)        {            return 419;        }# Authorization 绕过        if ($http_authorization != ””)        {            return 419;        }# WordPress 登录状态        if ($http_cookie ~*            ”(wordpress_logged_in|wp-postpass|comment_author)_”)        {            return 419;        }# WooCommerce Session        if ($http_cookie ~*            ”(woocommerce_items_in_cart|woocommerce_cart_hash|wp_woocommerce_session_)”)        {            return 419;        }# WordPress 动态接口        if ($uri ~*            ”^/(wp-admin|wp-login\.php|wp-json|xmlrpc\.php|wp-cron\.php|wp-comments-post\.php)”)        {            return 419;        }# WooCommerce 动态页面        if ($uri ~*            ”^/(cart|checkout|my-account)(/|$)”)        {            return 419;        }# 普通访客尝试缓存        return 418;    }# ================================================================# Cache Enabler HIT# ================================================================    location @cache_enabler    {        try_files $ce_cache_file @wordpress;        gzip off;        types { }        default_type text/html;        add_header Content-Encoding gzip always;        add_header Vary ”Accept-Encoding” always;        add_header X-Cache ”Cache-Enabler-HIT” always;    }# ================================================================# Cache MISS → WordPress# ================================================================    location @wordpress    {        try_files $uri $uri/ /index.php?$args;    }# ================================================================# 禁止 uploads 执行 PHP# ================================================================    location ~*        ^/wp-content/uploads/.*\.(php|php[0-9]+|phtml|phar)$    {        deny all;    }# ================================================================# PHP#    # 根据自己的宝塔 PHP 版本调整#    # ================================================================    include enable-php-81.conf;# ================================================================# 图片# ================================================================    location ~*        \.(gif|jpg|jpeg|png|bmp|webp|avif|ico|svg)$    {        expires 30d;        access_log off;        add_header Cache-Control ”public”;    }# ================================================================# CSS / JS# ================================================================    location ~* \.(css|js)$    {        expires 12h;        access_log off;        add_header Cache-Control ”public”;    }# ================================================================# 字体# ================================================================    location ~*        \.(woff|woff2|ttf|otf|eot)$    {        expires 30d;        access_log off;        add_header Cache-Control ”public”;    }# ================================================================# Let's Encrypt# ================================================================    location ^~ /.well-known/acme-challenge/    {        allow all;    }# ================================================================# 隐藏文件# ================================================================    location ~ /\.    {        deny all;    }}

宝塔环境需要特别注意:

如果原配置里存在:

include /www/server/panel/vhost/rewrite/example.com.conf;

或者已经存在:

location /

不要和上面的:

location /

重复使用。

因为新的:

location @wordpress{    try_files $uri $uri/ /index.php?$args;}

已经完成 WordPress Rewrite fallback。

十五、完整配置二:LNMP + WordPress + Cache Enabler

LNMP 常见:

网站目录:/home/wwwroot/example.comNginx 配置:/usr/local/nginx/conf/vhost/example.com.conf

完整配置如下:

server{    listen 80;    #listen [::]:80;    server_name example.com;    root /home/wwwroot/example.com;# ================================================================# 日志# ================================================================    access_log /home/wwwlogs/example.com.access.log;    error_log /home/wwwlogs/example.com.error.log warn;# ================================================================# Let's Encrypt# ================================================================    location ~ /.well-known    {        allow all;    }# ================================================================# 隐藏文件# ================================================================    location ~ /\.    {        deny all;    }# ================================================================# HTTP → HTTPS# ================================================================    location /    {        return 301 https://$host$request_uri;    }}server{    listen 443 ssl http2;    #listen [::]:443 ssl http2;    server_name example.com;    index index.html index.htm index.php default.html default.htm default.php;    root /home/wwwroot/example.com;# ================================================================# 日志# ================================================================    access_log /home/wwwlogs/example.com.access.log;    error_log /home/wwwlogs/example.com.error.log warn;# ================================================================# SSL# ================================================================    ssl_certificate        /usr/local/nginx/conf/ssl/example.com/fullchain.cer;    ssl_certificate_key        /usr/local/nginx/conf/ssl/example.com/example.com.key;    ssl_session_timeout 5m;    ssl_protocols TLSv1.2 TLSv1.3;    ssl_prefer_server_ciphers on;    ssl_ciphers        ”TLS13-AES-256-GCM-SHA384:        TLS13-CHACHA20-POLY1305-SHA256:        TLS13-AES-128-GCM-SHA256:        TLS13-AES-128-CCM-8-SHA256:        TLS13-AES-128-CCM-SHA256:        EECDH+CHACHA20:        EECDH+CHACHA20-draft:        EECDH+AES128:        RSA+AES128:        EECDH+AES256:        RSA+AES256:        EECDH+3DES:        RSA+3DES:        !MD5”;    ssl_session_cache builtin:1000 shared:SSL:10m;    ssl_dhparam        /usr/local/nginx/conf/ssl/dhparam.pem;# ================================================================# Cache Enabler# ================================================================    set $ce_device ””;# ------------------------------------------------# Mobile Cache# ------------------------------------------------    if ($http_user_agent ~*        ”(Mobile|Android|Silk/|Kindle|BlackBerry|Opera Mini|Opera Mobi|iPhone|iPod)”)    {        set $ce_device ”-mobile”;    }# ------------------------------------------------# Cache Enabler 文件# ------------------------------------------------    set $ce_cache_file        ”/wp-content/cache/cache-enabler/${host}${uri}https-index${ce_device}.html.gz”;# ================================================================# wp-admin 自动补 /# ================================================================    rewrite ^/wp-admin$ $scheme://$host$uripermanent;# ================================================================# WordPress 主入口# ================================================================    location /    {        recursive_error_pages on;        error_page 418 = @cache_enabler;        error_page 419 = @wordpress;# GET / HEAD        if ($request_method !~ ”^(GET|HEAD)$”)        {            return 419;        }# gzip        if ($http_accept_encoding !~* ”gzip”)        {            return 419;        }# URL 参数        if ($query_string != ””)        {            return 419;        }# Authorization        if ($http_authorization != ””)        {            return 419;        }# WordPress 登录        if ($http_cookie ~*            ”(wordpress_logged_in|wp-postpass|comment_author)_”)        {            return 419;        }# WooCommerce Session        if ($http_cookie ~*            ”(woocommerce_items_in_cart|woocommerce_cart_hash|wp_woocommerce_session_)”)        {            return 419;        }# WordPress 动态路径        if ($uri ~*            ”^/(wp-admin|wp-login\.php|wp-json|xmlrpc\.php|wp-cron\.php|wp-comments-post\.php)”)        {            return 419;        }# WooCommerce 动态页面        if ($uri ~*            ”^/(cart|checkout|my-account)(/|$)”)        {            return 419;        }        return 418;    }# ================================================================# Cache Enabler HIT# ================================================================    location @cache_enabler    {        try_files $ce_cache_file @wordpress;        gzip off;        types { }        default_type text/html;        add_header Content-Encoding gzip always;        add_header Vary ”Accept-Encoding” always;        add_header X-Cache ”Cache-Enabler-HIT” always;    }# ================================================================# Cache MISS → WordPress# ================================================================    location @wordpress    {        try_files $uri $uri/ /index.php?$args;    }# ================================================================# 禁止 uploads PHP# ================================================================    location ~*        ^/wp-content/uploads/.*\.(php|php[0-9]+|phtml|phar)$    {        deny all;    }# ================================================================# PHP# ================================================================    include enable-php.conf;# ================================================================# 图片# ================================================================    location ~*        \.(gif|jpg|jpeg|png|bmp|swf|webp|avif|ico|svg)$    {        expires 30d;        access_log off;        add_header Cache-Control ”public”;    }# ================================================================# CSS / JS# ================================================================    location ~* \.(js|css)$    {        expires 12h;        access_log off;        add_header Cache-Control ”public”;    }# ================================================================# 字体# ================================================================    location ~*        \.(woff|woff2|ttf|otf|eot)$    {        expires 30d;        access_log off;        add_header Cache-Control ”public”;    }# ================================================================# Let's Encrypt# ================================================================    location ~ /.well-known    {        allow all;    }# ================================================================# 隐藏文件# ================================================================    location ~ /\.    {        deny all;    }}

LNMP 如果原配置存在:

include rewrite/wordpress.conf;

使用这套配置以后,需要删除或注释:

# include rewrite/wordpress.conf;

否则可能和新的 WordPress fallback 重复。

十六、修改之前一定备份

例如:

cp example.com.conf \example.com.conf.bak-cache

宝塔也建议先复制原配置。

然后:

nginx -t

或:

/usr/local/nginx/sbin/nginx -t

测试通过以后再 reload。

千万不要:

修改配置 ↓直接重启

如果 Nginx 配置写错,线上网站可能直接打不开。

十七、最终验证方法

第一步:

curl -I \-H ”Accept-Encoding: gzip” \https://example.com/

期待:

x-cache: Cache-Enabler-HIT

第二步:

检查:

x-powered-by: PHP

是否消失。

第三步:

测试一个明确已经存在缓存的内页:

curl -I \-H ”Accept-Encoding: gzip” \https://example.com/product/example-product/

同样应该:

x-cache: Cache-Enabler-HIT

第四步:

测试一个不存在的页面:

curl -I \-H ”Accept-Encoding: gzip” \https://example.com/cache-test-not-exist/

应该正常进入 WordPress,然后返回:

404

而不是把错误页面当缓存返回。

十八、写在最后

这次重新折腾 WordPress 缓存之后,我最大的一个认识就是:

缓存插件“工作正常”和服务器“真正使用缓存”,完全是两个概念。

很多时候我们看到:

Cache Enabled

看到:

wp-content/cache/

里面已经有很多文件,就认为优化完成了。

其实请求可能还是:

Nginx ↓PHP ↓WordPress ↓MySQL

而我现在更愿意直接确认:

X-Cache: Cache-Enabler-HIT

然后看:

x-powered-by: PHP

是否消失。

只有这样,我才认为:

服务器真正绕过了 WordPress 动态执行。

对于内容型 WordPress 网站,我现在比较喜欢这样的结构:

CDN ↓Nginx ↓静态 HTML

只有真正需要动态内容的时候:

Nginx ↓PHP ↓WordPress ↓MySQL

这种思路并不复杂,但实际效果非常直接。

最后还是那句话:

服务器优化第一原则不是追求极限速度,而是保证稳定。

所以任何线上环境修改之前:

先确认缓存文件 ↓先备份 ↓修改配置 ↓nginx -t ↓确认成功 ↓reload ↓curl 验证

一步都不要省。

当你真正看到:

x-cache: Cache-Enabler-HIT

并且:

x-powered-by: PHP

消失的时候,才说明这次 WordPress 静态缓存优化真正完成了。

相关学习资料

返回首页浏览学习资料