独立站缓存策略:页面缓存、对象缓存、浏览器缓存的配置

独立站性能优化里,缓存是投入产出比最高的一步——只配页面缓存,就能让LCP从4秒降到1秒以内。三层缓存各管一段:页面缓存管HTML,对象缓存管数据库查询结...

三层缓存:每层管一段,不能混Three cache layers: each owns a segment, don’t mix 页面缓存管HTML · 对象缓存管数据库查询 · 浏览器缓存管静态资源Page=HTML · Object=DB queries · Browser=static assets ① 页面缓存 Page Cache —— 把整个HTML存起来,下次直接返回① Page Cache — store full HTML, return it next time 缓存时间:静态页面1小时至1天 · 表单页/wp-admin永不缓存TTL: static pages 1h-1d · forms/wp-admin never cached ② 对象缓存 Object Cache —— 把数据库查询结果存到Redis/Memcached② Object Cache — store DB query results in Redis/Memcached TTL:对象缓存12小时至7天 · 内容更新时主动失效TTL: 12h-7d · invalidate on content update ③ 浏览器缓存 Browser Cache —— 用Cache-Control头让访客本地存静态资源③ Browser Cache — use Cache-Control header to cache locally TTL:图片30天至1年 · CSS/JS 7天 · 文件名带hash自动失效TTL: images 30d-1y · CSS/JS 7d · hash-based invalidation 优先级:页面缓存 > 对象缓存 > 浏览器缓存(先配最值钱的)Priority: page > object > browser (do the highest-value first) 只配页面缓存就能让LCP从4秒降到1秒以内,对象缓存是加分项Page cache alone cuts LCP from 4s to under 1s; object cache is bonus 反直觉:缓存不是越多越好,表单页缓存了会泄露别人的提交Counter-intuitive: caching forms leaks other users’ submissions 询盘表单、wp-admin、购物车、登录后页面必须no-cacheInquiry forms, wp-admin, cart, logged-in pages must be no-cache 浏览器缓存不是越长越好:用文件hash解决”改了看不到”Browser TTL isn’t longer=better: use file hashes for updates
独立站三层缓存策略:页面缓存、对象缓存、浏览器缓存的分工与TTL配置

独立站缓存策略:页面缓存、对象缓存、浏览器缓存的配置

结论先行:独立站性能优化里,缓存是投入产出比最高的一步——只配页面缓存,就能让LCP从4秒降到1秒以内。三层缓存各管一段:页面缓存管HTML,对象缓存管数据库查询结果,浏览器缓存管静态资源。TTL建议:静态页面缓存1小时至1天,对象缓存12小时至7天,图片浏览器缓存30天至1年。反直觉判断:缓存不是越多越好——询盘表单、wp-admin、登录后页面必须no-cache,否则用户会看到别人提交的内容。配置顺序是先页面缓存、再对象缓存、最后浏览器缓存,不要倒过来。

一、三层缓存各自管什么

独立站的缓存可以分三层,每层解决不同的问题,不要混为一谈。页面缓存把整个HTML渲染结果存成静态文件,下次有人访问同一个URL直接返回文件,不用再跑PHP和数据库。对象缓存把数据库查询的结果存到内存(如Redis或Memcached),下次同样的查询直接从内存拿,不用再查MySQL。浏览器缓存用HTTP响应头告诉访客的浏览器”这个文件你本地存着”,下次访问直接从本地磁盘读。

三层的性能收益差别很大。页面缓存收益最大——它把PHP执行和数据库查询整个跳过,LCP能从4秒以上降到1秒以内。对象缓存收益中等——它只省掉数据库查询时间,页面缓存已经命中的话,对象缓存根本不会被触发。浏览器缓存收益针对回访访客——第一次访问必须下载,第二次起本地读,回访速度提升明显。

缓存层 存什么 存在哪里 性能收益 典型工具
页面缓存 完整HTML页面 服务器磁盘或内存 最大,LCP降60%至80% WP Rocket、LiteSpeed Cache
对象缓存 数据库查询结果、PHP对象 Redis或Memcached 中等,DB查询时间降50% Redis、Memcached
浏览器缓存 CSS/JS/图片 访客浏览器本地 回访访客,二次访问快 Cache-Control响应头
CDN缓存 静态资源+部分HTML 全球边缘节点 跨地域延迟降50%以上 Cloudflare、Akamai

很多人一上来就折腾Redis和Memcached,其实对B2B独立站来说,配好页面缓存已经解决了80%的性能问题。对象缓存是加分项,适合月UV超过5万或数据库查询变慢的时候再上。CDN和三层缓存的关系见CDN全球加速与节点选择,性能指标的合格线见Core Web Vitals优化。

二、页面缓存:HTML怎么存才不出错

页面缓存是最值钱的一层,也是最容易配错的一层。配错的典型症状是:访客提交询盘后,看到的是上一个访客的提交内容;或者用户登录后看到的还是未登录状态的页面。原因是页面缓存把带动态内容的HTML也存成了静态文件。

正确的做法是按URL和用户状态分两类:公开静态页面(首页、产品页、博客文章页)走页面缓存;动态页面(询盘表单提交后、wp-admin后台、登录后页面、购物车)必须跳过缓存。WordPress的缓存插件(WP Rocket、LiteSpeed Cache)都支持”排除URL”和”按Cookie跳过缓存”的规则。

页面类型 是否缓存 缓存时间 排除规则
首页、产品列表页 缓存 1小时至4小时 登录用户排除
博客文章页 缓存 12小时至1天 内容更新时手动刷新
询盘表单页 不缓存 不设 永远回源
表单提交成功页 不缓存 不设 带session cookie
wp-admin后台 不缓存 不设 管理员cookie排除
搜索结果页 短缓存或不缓存 5分钟 避免缓存不同搜索词

场景示例:一个工业装备官网的产品详情页,URL是 /products/cnc-machine-a/,这个页面内容几个月才改一次,完全可以缓存1天。但询盘表单的”提交成功”页面URL是 /inquiry-thank-you/,这个页面每个访客看到的内容应该是自己提交的确认信息,绝对不能缓存。在WP Rocket里,把 /inquiry-thank-you/ 和 /wp-admin/* 加到Never Cache URL(s)列表里。

缓存失效也是页面缓存的关键。改了一篇博客文章,怎么让线上立刻生效?两种方式:一种是发布时手动Purge全部缓存,另一种是用”按URL刷新”只清那一篇。WP Rocket在文章更新时会自动刷新相关缓存,但很多自定义页面不会自动触发,需要养成发布后点一下Purge的习惯。环形山在出海站里把缓存失效和发布流程绑定,详见环形山技术栈与四个自研插件。

三、对象缓存:数据库查询结果怎么复用

页面缓存命中的时候,PHP和数据库都不会跑,对象缓存自然也用不上。但当页面缓存没命中时——比如你刚发布了一篇新文章、或者访问了一个不该缓存的动态页面——PHP就要查数据库了。一个WordPress页面平均要查12至20次数据库,每次查询都走磁盘IO,慢查询累积起来就能让页面耗时超过1秒。

对象缓存把这些查询结果存到Redis或Memcached里,下次同样的查询直接从内存读。Redis在单台服务器上装一下,WordPress用Redis Object Cache插件接入,不需要改任何代码。配置正确的话,数据库查询时间能降50%以上,页面缓存miss时的响应时间也能从1.5秒降到0.5秒以内。

指标 无对象缓存 有Redis对象缓存 提升幅度
页面数据库查询次数 12至20次/页 2至5次/页 减少70%至80%
单次查询耗时 5至20毫秒(磁盘IO) 0.1至1毫秒(内存) 快10至50倍
页面缓存miss时响应时间 1至1.5秒 0.3至0.5秒 降50%以上
MySQL CPU占用 高峰80%以上 高峰30%至40% 降一半以上

对象缓存不是必须上的。月UV在1万以下的B2B站,数据库压力不大,页面缓存已经扛住了95%的请求,上Redis的收益不明显。什么时候该上?两个信号:一是MySQL慢查询日志里每天有超过100条查询超过1秒;二是后台编辑文章时,保存后前台要等好几分钟才生效(对象缓存没正确失效)。数据库慢查询和索引优化见独立站数据库慢查询与索引优化。

四、浏览器缓存:静态资源的缓存头怎么设

浏览器缓存是三层里最容易配置的一层,它不涉及服务器端任何程序,只要在Web服务器(Nginx或Apache)加几行响应头就行。原理是:服务器在返回CSS、JS、图片时,在HTTP响应头里加Cache-Control: max-age=2592000,告诉浏览器”这个文件你本地存30天”,30天内再访问就不请求服务器了。

但这里有一个经典矛盾:浏览器缓存时间设长了,用户访问很快;但你改了CSS或JS,用户本地还是旧版本,看到的页面样式不对。解决方法不是把缓存时间设短,而是给文件名加版本号或hash——比如 style.css?v=2 或 style.abc123.css,文件内容变了,URL就变了,浏览器自动重新下载。

资源类型 Cache-Control建议 max-age 更新策略
图片(jpg/png/webp) public, max-age=31536000 1年 文件名带hash,换图即换名
字体文件 public, max-age=31536000 1年 字体不变不用改
CSS样式表 public, max-age=604800 7天 文件名带版本号?ver=2
JavaScript public, max-age=604800 7天 文件名带版本号?ver=2
HTML页面 no-cache, must-revalidate 不缓存 每次回源验证
favicon.ico public, max-age=604800 7天 很少改

反直觉判断:很多人怕缓存时间长了改内容用户看不到,于是把所有资源的max-age都设成1小时。结果是每个访客每次访问都重新下载全部CSS和JS,首屏时间反而变慢。正确做法是大胆设长(图片1年、CSS/JS 7天),但用文件hash或版本号解决更新问题。WordPress的wp_enqueue_script函数自动加版本号,主题和插件更新时版本号会自动变,不需要手动管。

图片优化和媒体资产治理见媒体资产治理与图片压缩。多语言站的静态资源缓存还要注意hreflang和CDN缓存的交互,见Hreflang多语言落地。

五、缓存失效策略与常见冲突

缓存配好之后,最大的问题是”怎么让缓存该过期的时候过期”。缓存没及时失效,用户看到旧内容;缓存太容易失效,性能收益又没了。独立站常见的缓存失效场景有四个:发布新文章、更新产品信息、修改CSS/JS、提交询盘表单。每个场景对应不同的失效策略。

场景 失效范围 失效方式 注意事项
发布新博客文章 首页+文章列表+单篇 WP Rocket自动刷新 分类页和标签页也要刷新
更新产品价格 产品详情页+列表页 手动Purge对应URL 不要Purge全部,影响性能
改CSS/JS 对应静态文件 改版本号自动生效 不要改max-age,改文件名
提交询盘表单 表单页永不缓存 URL排除规则 成功页也不能缓存
全站改版 全部缓存 一键Purge All 选在低峰期做
更新插件/主题 全部缓存 自动或手动Purge 更新前先备份

常见冲突有两个:一是装了两个缓存插件(比如同时装WP Rocket和LiteSpeed Cache),两个插件都在改.htaccess和输出缓冲,结果页面白屏或样式错乱。规则是全站只装一个缓存插件。二是页面缓存和登录状态冲突——用户登录了后台,前台还是缓存的未登录页面,看到的导航栏不对。解决方法是缓存插件识别登录cookie后自动跳过缓存。

缓存策略上线后要持续监控,每月检查一次缓存命中率和LCP。缓存命中率突然下降,通常是有人改了URL结构或加了带随机参数的链接。监控和告警清单见站点监控与告警,日常维护事项见官网维护期每月六件事。备份和恢复演练也要在缓存配置变更后做一次,见网站备份与恢复演练。

FAQ 常见问题

WordPress独立站必须装缓存插件吗?
月UV在1万以上的站必须装。只配页面缓存这一项,就能让LCP从4秒以上降到1秒以内,是投入产出比最高的优化。推荐WP Rocket或LiteSpeed Cache,二选一,不要同时装两个。月UV在1000以下的小站,共享主机上PHP本身就快,不装缓存插件也能跑,但装了也没坏处。
询盘表单页能不能缓存?
绝对不能。表单页和提交成功页必须设为no-cache。如果缓存了,下一个访客打开表单时看到的是上一个访客填写的内容,提交的数据会混在一起。在WP Rocket里把/inquiry*、/thank-you*、/wp-admin/*加到Never Cache URL(s)列表。同时确保缓存插件识别登录cookie后自动跳过缓存。
Redis对象缓存什么时候该上?
两个信号出现时再上:一是MySQL慢查询日志每天有超过100条查询超过1秒;二是后台保存文章后前台要等好几分钟才生效。月UV在1万以下的B2B站,数据库压力不大,页面缓存已经扛住95%请求,上Redis收益不明显。月UV超过5万或数据库成为瓶颈时,再装Redis+Redis Object Cache插件。
浏览器缓存时间设多久合适?
图片和字体设1年(max-age=31536000),CSS和JS设7天(max-age=604800),HTML不缓存。不要因为怕改了内容用户看不到就把时间设短——那样每个访客每次都重新下载,首屏反而慢。解决更新问题的方法是给文件名加版本号或hash,比如style.css?v=2,内容变了URL就变了,浏览器自动重新下载。
缓存改了内容用户看不到怎么办?
分两种情况。如果是CDN缓存,去CDN后台手动Purge对应URL或全部;如果是服务器端页面缓存,WP Rocket和LiteSpeed Cache在文章更新时会自动刷新相关缓存,但自定义页面和分类页可能需要手动Purge。如果是浏览器缓存,说明文件名没变,下次发布时给静态文件加版本号。不要把max-age改短来解决这个问题,那是因噎废食。
页面缓存和CDN缓存会不会冲突?
不会冲突,它们是上下游关系。CDN缓存边缘节点到用户这一段,服务器端页面缓存管源站这一段。正确的配合是:HTML由服务器端页面缓存生成,CDN对HTML设no-cache短TTL或不缓存,只缓存图片CSS JS。如果CDN也把HTML缓存了,又和服务器端页面缓存叠在一起,用户提交表单后看到旧内容的概率会大增。

写在最后

缓存这件事,新手最容易走两个极端:要么完全不配,每个页面都现跑PHP和数据库,首屏4秒以上;要么配得太激进,把表单页也缓存了,结果用户看到别人的提交内容。正确的思路是”分层处理”——静态页面大胆缓存,动态页面坚决不缓存,静态资源长缓存加版本号。

落地三步:第一步,装一个页面缓存插件(WP Rocket或LiteSpeed Cache二选一),把表单页和wp-admin排除;第二步,配Nginx的Cache-Control头,图片1年、CSS/JS 7天、HTML不缓存;第三步,月UV超过5万时再上Redis对象缓存。这三步做完,LCP基本能压到1秒以内,而且不会出现缓存串内容的事故。

一句可以记住的话:缓存是独立站性能的杠杆——页面缓存省80%时间,对象缓存省数据库,浏览器缓存省回访,三层各管一段,别让表单页进了缓存。

环形山
环形山 环形山专家

机构官方 · 环形山 Crater

环形山(Crater)是一家专注 WordPress 独立站开发 + Google SEO + GEO 全域增长的出海服务公司,服务智能硬件、工业装备、SaaS、新能源等赛道。

产品能力方法论白皮书行业报告
965篇分享
78篇知识库