你有没有试过清完缓存,网站反而更慢了?
别笑——真有人这么干过。
明明图片压缩了、代码拆分了、CDN也开了,可用户一刷页面还是卡顿,后台日志里全是重复请求。问题大概率不在服务器,而在你没管好的浏览器缓存:它不是没在工作,而是“太听话”地缓存了不该缓存的东西,或者“太固执”地拒绝更新该换的文件。
浏览器缓存到底在“缓存”什么?
浏览器缓存,说白了就是把网页用到的文件(比如一张Logo图、一段CSS样式、一个JS脚本)悄悄存在用户电脑里。下次打开同一页面时,它就直接从本地拿,不用再跑一趟服务器。
这些文件分两类:
- 静态资源:Logo、图标、字体、通用CSS/JS库——内容稳定,改得少,适合多存几天;
- 动态资源:用户头像、购物车数量、评论列表——随时可能变,缓存太久会显示旧数据。
我们帮一家本地家居电商优化时发现:他们所有按钮图标都用雪碧图(sprite),但响应头里压根没写任何缓存指令。结果每次进商品页,几十KB的图标都要重下一遍。加了一行 Cache-Control: public, max-age=31536000 后,回访用户点开详情页,明显快了一截。
强缓存与协商缓存,你该用哪把“锁”?
强缓存和协商缓存不是二选一,是分工合作:
- 强缓存:浏览器一看
Cache-Control或Expires还没过期,连服务器都不问,直接上本地文件。快,但风险是更新不及时。 - 协商缓存:浏览器先问服务器一句:“我手里的
main.css还新鲜吗?”服务器如果回个304 Not Modified,它就安心用本地的;如果文件真变了,才下载新的。
实际怎么配?
- 公司Logo、带哈希名的JS/CSS(比如
app.8d2e.js)——直接上强缓存,设一年; - 没加哈希的通用样式表(如
common.css)——用协商缓存 + 一天强缓存兜底,既防误伤,又保速度。
Cache-Control指令,你的缓存“遥控器”
Cache-Control 是现代缓存的总开关,几个常用指令得拎得清:
max-age=31536000:缓存一年(单位是秒);public:允许浏览器和中间代理(比如公司WiFi网关)一起缓存;private:只给当前用户浏览器存,别让别人看见;no-cache:不是不存,是“用之前必须找服务器确认一遍”;no-store:真·不存,敏感信息(如支付结果页)才用它;immutable:告诉浏览器“这文件一年内绝不会变,刷新也不用验证”,省掉一次HTTP请求。
我们给一个SaaS后台配缓存时,对所有带哈希的静态资源统一加了这句:Cache-Control: public, max-age=31536000, immutable
上线后,老用户反复切换菜单页,几乎看不到网络请求在动。
如何给不同资源制定缓存策略?
别一股脑全设成 max-age=31536000。按文件“脾气”分类处理更靠谱:
- 永久不变的(带哈希的JS/CSS/图片):
Cache-Control: public, max-age=31536000, immutable - 很少变的(
reset.css、iconfont.woff2):Cache-Control: public, max-age=86400+ETag - 经常变的(首页HTML、API返回的JSON):
Cache-Control: no-cache或max-age=60 - 绝对实时的(订单支付状态页、私信列表):
Cache-Control: no-store
有个细节注意:HTML文件本身尽量别设长缓存。它就像个“目录”,里面引用的JS/CSS才是重点。目录常更新,内容才稳。
更新了文件,用户却看不到怎么办?
这是最扎心的场景:你凌晨三点发版,早上客户说“怎么还是旧按钮?”
核心解法就一个:让新文件看起来是“新URL”。
最佳实践是“文件指纹”——构建时自动给文件名加哈希,比如 button.js → button.a7f3b9.js。内容一变,哈希就变,URL就变,浏览器自然当它是新资源,重新下载。
如果你暂时没法改构建流程,退而求其次:在HTML里引用时手动加版本号,比如 <script src="app.js?v=20240520">。但得提醒运维,有些老旧CDN或代理会忽略 ?v= 后面的部分,不如指纹可靠。
实战检查:你的缓存设置生效了吗?
别猜,直接看。
打开 Chrome 或 Edge,按 F12 → 切到 Network 标签页 → 刷新页面 → 点开任意一个JS或CSS请求 → 往下拉看 Response Headers。
重点盯三行:
Cache-Control(有没有?值对不对?)ETag或Last-Modified(协商缓存有没有配?)- Size列显示的是
memory cache还是具体字节数(前者说明真从缓存读的)
我们曾帮一家教育平台排查,发现他们明明写了 max-age=31536000,但Network里全是 from disk cache 却加载慢。一查,是CDN配置把源站的 Cache-Control 头给覆盖掉了。最后在CDN后台补上透传规则,问题当场解决。
今天下班前就能执行的一个具体步骤
现在,打开你正在维护的那个网站(比如后台管理页、产品列表页),按 F12 打开开发者工具 → Network → 刷新页面。
在过滤栏输入 img,把所有图片请求列出来;再分别输 css 和 js,把样式和脚本也筛出来。
挨个点开它们的响应头,找有没有 Cache-Control。
如果看到 logo.png、vendor.7a2b.js 这类静态文件的响应头里是空的,或者写着 no-cache,那就记下它的路径(比如 /static/images/logo.png)。
然后,打开你常用的运维协作工具(比如公司用的钉钉群、飞书文档、或Jenkins构建页),发一条消息:
“麻烦帮忙给
/static/和/assets/目录下的所有.png/.jpg/.css/.js文件,统一加上这行响应头:Cache-Control: public, max-age=86400。测试环境先配,没问题再上生产。”
这事不用改代码,不用动构建,运维同事配个Nginx location规则或CDN缓存策略,5分钟搞定。明天你再F12看一眼,那些图片和JS的Size栏,大概率就变成 memory cache 了。