在日常检查本站的时候,发现使用主题自定义首页模块显示出现 bug,于是进入排查,我在后台设置首页模块添加了三类模块(PC,移动,双端显示),在开启 Nginx FastCGI 缓存后,PC 端首页正常,而移动端显示不出移动端专属首页模块,查看页面源码后发现只有 PC 端模块的元素(mobile-hidden) 和双端模块元素,手机只能显示双端模块,因此断定为 Nginx FastCGI 缓存 PC 端和移动端双端未分离导致。所以,问题的根因是:“同一个 URL(比如首页)被 Nginx 层缓存了,而且缓存键没有区分 PC / 移动,导致手机端一直吃到 PC 的 HTML。”
解决方法
1. 修改 Nginx 配置文件
在 http 块增加 UA 判别变量(区分 PC / 移动)
宝塔面板:软件商店 → Nginx → 设置 → 配置修改(http 块里,一般是 server 块之前)增加:
# 区分 PC / 移动(按需要调整 UA 关键字)
map $http_user_agent $is_mobile {
default 0;
~*mobile 1;
# 如果需要更细致,可以按下面这份来(和很多教程类似)
# ~*(android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)| plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino) 1;
}
这个map会根据 UA 把 $is_mobile 设为 0(PC)或 1(移动)。
2. 分别定义 PC / 移动两份缓存路径
在 http 块里(还是上面那个位置)添加两个 cache_path:
# PC 缓存
fastcgi_cache_path /dev/shm/nginx-cache/wp/pc levels=1:2 keys_zone=pc_cache:128m inactive=1d max_size=1g;
# 移动缓存
fastcgi_cache_path /dev/shm/nginx-cache/wp/mobile levels=1:2 keys_zone=mobile_cache:128m inactive=1d max_size=1g;
如果你已经有 fastcgi_cache_path,可以把原先的注释掉或删掉,改成上面两行。注意目录 /dev/shm/nginx-cache/wp/ 可根据你的实际情况调整。
3. 在网站 server 块里根据 UA 选择不同的 cache_zone
宝塔面板:网站 → 设置 → 配置文件,在 server 块中(通常在 set $skip_cache 0; 附近,没找到也无所谓)加:
# 默认用 PC 缓存
set $cache_zone "pc_cache";
# 如果是移动端,改用 mobile 缓存
if ($is_mobile) {
set $cache_zone "mobile_cache";
}
4.继续修改站点配置
因为我使用的是宝塔面板的 WP Tools 套件建站,因此指定配置文件修改为 enable-php-83-wpfastcgi.conf,这是宝塔专门为 WordPress FastCGI 缓存准备的配置文件,里面已经写好了所有必要的缓存逻辑($skip_cache 判断、缓存开关、安全头部、以及最关键的缓存清理接口 /purge)。
找到:
#PHP-INFO-START PHP引用配置,可以注释或修改
include enable-php-83.conf;
#PHP-INFO-END
把它改成:
#PHP-INFO-START PHP引用配置,可以注释或修改
include enable-php-83-wpfastcgi.conf;
#PHP-INFO-END
(注意:你之前在 server 块里添加的 set $cache_zone ... 和 if ($is_mobile) ... 代码保留,不要删,它们待会儿会被这个文件调用。)
5. 修改 enable-php-83-wpfastcgi.conf 文件
这是最核心的一步。我们需要让这个文件使用你之前在 nginx.conf 里定义的两个独立缓存区(pc_cache 和 mobile_cache),并在缓存键里加上设备标识。
请编辑文件:/www/server/nginx/conf/enable-php-83-wpfastcgi.conf
按下面的说明修改 3 个地方:
1 修改缓存区指令
找到这一行:
fastcgi_cache WORDPRESS;
修改为(使用变量,自动切换 PC/Mobile 缓存区):
fastcgi_cache $cache_zone;
2 添加缓存键
在刚才那行 fastcgi_cache … 的下面,新加一行:
fastcgi_cache_key "$scheme$request_method$host$is_mobile$request_uri";
(这行非常关键,确保 PC 和 Mobile 的缓存文件分开存放)
3)修改缓存清理规则
找到文件最后的 location ~ /purge(/.*) 部分:
原内容可能是:
location ~ /purge(/.*) {
allow 127.0.0.1;
deny all;
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
}
修改为(让它分别清理 PC 和 Mobile 两个缓存区):
location ~ /purge_pc(/.*) {
allow 127.0.0.1;
deny all;
fastcgi_cache_purge pc_cache "$scheme$request_method${host}0$1";
}
location ~ /purge_mobile(/.*) {
allow 127.0.0.1;
deny all;
fastcgi_cache_purge mobile_cache "$scheme$request_method${host}1$1";
}
缓存清理
修改 Nginx Helper 插件核心文件
网站根目录/wp-content/plugins/nginx-helper/admin/class-fastcgi-purger.php
你现在的 purge_url() 里关键部分是这样的:
case 'get_request':
// Go to default case.
default:
$_url_purge_base =$this->purge_base_url() . $parse['path'];
$_url_purge =$_url_purge_base;
if ( isset( $parse['query'] ) && '' !==$parse['query'] ) {
$_url_purge .= '?' .$parse['query'];
}
$this->do_remote_get($_url_purge );
if ( $feed && ! empty($nginx_helper_admin->options['purge_feeds'] ) ) {
$feed_url = rtrim($_url_purge_base, '/' ) . '/feed/';
$this->do_remote_get($feed_url );
$this->do_remote_get($feed_url . 'atom/' );
$this->do_remote_get($feed_url . 'rdf/' );
}
break;
重点就是:
$this->purge_base_url() 会拼出类似 https://你的域名/purge 这样的基础路径
然后 $_url_purge 拼上 path 和 query,就是具体要清理的 URL,比如:
https://域名/purge/some-post
然后通过 $this->do_remote_get($_url_purge ); 发起请求
改成:
case 'get_request':
// Go to default case.
default:
$_url_purge_base =$this->purge_base_url() . $parse['path'];
$_url_purge =$_url_purge_base;
if ( isset( $parse['query'] ) && '' !==$parse['query'] ) {
$_url_purge .= '?' .$parse['query'];
}
// 1) 清理 PC:把 /purge/ 换成 /purge_pc/
$_url_purge_pc = str_replace('/purge/', '/purge_pc/',$_url_purge);
$this->do_remote_get($_url_purge_pc );
// 2) 清理 Mobile:把 /purge/ 换成 /purge_mobile/
$_url_purge_mobile = str_replace('/purge/', '/purge_mobile/',$_url_purge);
$this->do_remote_get($_url_purge_mobile );
if ( $feed && ! empty($nginx_helper_admin->options['purge_feeds'] ) ) {
$feed_url = rtrim($_url_purge_base, '/' ) . '/feed/';
// PC feed
$feed_url_pc = str_replace('/purge/', '/purge_pc/',$feed_url);
$this->do_remote_get($feed_url_pc );
$this->do_remote_get($feed_url_pc . 'atom/' );
$this->do_remote_get($feed_url_pc . 'rdf/' );
// Mobile feed
$feed_url_mobile = str_replace('/purge/', '/purge_mobile/',$feed_url);
$this->do_remote_get($feed_url_mobile );
$this->do_remote_get($feed_url_mobile . 'atom/' );
$this->do_remote_get($feed_url_mobile . 'rdf/' );
}
break;
缓存清理验证
1保存文件。
2在 WordPress 做一个会触发清理的操作,比如:
发布/修改一篇文章;
或者在后台工具栏点 “Purge Cache”(如果配置了的话)。
3看 Nginx 缓存文件夹 /dev/shm/nginx-cache/wp/ 的大小:
如果看到整个目录已经变成 0B,就说明插件修改生效,已经自动清理双端缓存了。
© 版权声明
本文采用 知识共享署名-非商业性使用 4.0 国际许可协议(CC BY-NC 4.0) 进行许可
转载必须 注明原作者+原文链接,不得篡改来源
仅限非商业用途,禁止用于盈利性场景(广告/付费专栏等)
可修改衍生,衍生作品需同步遵循本协议
不得删除或修改本文版权声明及核心信息
本站部分文章可能为网络转载,转载已尽力标注原作者及来源,旨在分享优质内容;若涉及版权争议或侵权,请联系我们及时删除,感谢理解与配合。
商用需授权 | 官方协议:CC BY-NC 4.0 全文

看到这种坑,感觉站长都被逼疯了