CDN 刷新过了,为什么还有用户看到旧页面?
CDN 刷新过、用户还是看到旧页面,多数时候问题不在刷新动作本身,而在于旧副本分散在好几层缓存里,只清掉了其中一层。2026 年常见的项目里,同一个「页面没更新」可能来自浏览器强缓存、CDN 边缘节点、Service Worker、小程序本地包中的任意一层。核对顺序建议固定为「入口 HTML 的响应头 → 静态资源文件名是否带内容指纹 → CDN 刷新与预热记录 → 客户端缓存层版本」,按这个顺序走,多数情况在发版当天就能定位,不必先回头怀疑代码。
为什么刷新了 CDN,旧页面还是能出现
入口 HTML 文件名固定、每次发布内容都会变;JS、CSS、图片这类资源通常靠文件名里的内容指纹区分版本。这两类文件如果用了同一条缓存规则,出现「刷了新还有旧页面」的概率就会明显上升。
- 浏览器 HTTP 缓存:强缓存命中时不回源,协商缓存才会发一次校验请求。
- CDN 边缘节点:各自按 TTL 保留副本,节点多的时候生效窗口是分散的。
- Service Worker:装过离线缓存的站点,旧 worker 有可能先把旧文件应答出去。
- 小程序本地包与 App 内置页:小程序有本地包更新机制,App 内置 H5 随 App 版本走。
- 用户本地存储:配置或灰度开关存在本地,键没换,行为看起来仍像旧版。
这几层的验证手段完全不同:浏览器层看响应头,CDN 层换个网络或换台设备就能复现差异,客户端那几层需要用户配合更新。用同一次「重新打包上传」去覆盖所有症状,是返工的主要来源。
按入口到资源的顺序核对,比重新打包省时间
先看入口,是因为入口决定了用户接下来会去请求哪些文件。入口还指着旧资源,后面怎么刷新都白费。这套顺序在交付现场通常比直接在代码里翻找更省时间。
- 核对入口 HTML 的响应头:看 Cache-Control 与 CDN 规则。常见交付口径是入口走协商缓存或很短的强缓存,经验区间在 0~5 分钟量级,保证每次访问都会校验一次。
- 核对静态资源指纹:JS、CSS、图片按内容哈希命名,文件名一变就是新资源,可以放心给长缓存,常见区间在 30 天到 1 年。这一步要确认构建产物真的带哈希,不少人以为有,实际是固定文件名。
- 核对 CDN 刷新与预热:确认发布环节里有没有刷新目录或指定 URL 这一步,刷新生效时间按经验在几分钟量级,节点覆盖广的项目会更久。
- 核对客户端缓存层:Service Worker 是否换了版本号、小程序是否走版本更新提示、App 内置包是否随发版一起换。
验收口径可以这样定:用无痕窗口访问一次,再换一个网络环境访问一次,两次都拿到新版本,才算这一层过关。只在自己电脑上刷新看到新版,不能作为发布完成的依据。
几种发布配置的生效窗口与代价
缓存策略没有通用答案,取舍主要在「改动多久能到用户」和「重复访问有多快」之间。下面三种是 2026 年项目里比较常见的做法,可以按业务对版本敏感的程度来选。
- 入口协商缓存 + 带哈希的资源长缓存:适合迭代频繁、对内容时效敏感的网站与 H5。发布后生效窗口按经验多在 0~5 分钟量级,代价是每次访问多一次协商请求。
- 全站短缓存:适合发布频率低、暂时不想维护资源哈希的早期项目。生效窗口与设置的 max-age 同量级,通常是几分钟,这段时间里仍会有部分用户看到旧页面。
- 全站长缓存 + 发布时手动刷 CDN:适合有固定发布窗口、能把刷新写进流程的团队。生效取决于有没有刷到,漏刷一次挂旧的时长按经验可能是几小时到数天,风险集中在这里。
判断标准不是谁更快,而是发布后多久所有用户都能拿到新版本,同时不把首屏拖慢。团队还没有发布清单时,先补清单再细化缓存头,顺序反了改动容易失控。
交付现场:一次旧版本挂了两天的代价
类似情况在交付现场不算少见:预算和周期都压得紧,发布脚本沿用了上一版,只改了构建目录,没有同步调整入口 HTML 的缓存头。上线后陆续有用户反馈页面没更新,前端先怀疑打包,重新构建又发了一次,现象依旧;后来在响应头里看到 HTML 还带着较长的强缓存时间,才定位到根因。代价通常是两次无意义的发布、一两天量级的返工,加上客服侧一批重复沟通,属于常见区间。后来把缓存头、资源哈希、CDN 刷新、客户端更新提示写成发布清单里的固定四项,和构建上传放在同一个步骤里执行,这类问题在后续版本里基本没再集中出现。
适用场景与边界
缓存分层这件事,在多端同时发布、又有 CDN 的项目里回报比较明显。用户对「看到的是不是最新内容」敏感的业务,比如活动页、价格页、订单与库存页,值得把这条链路做细。
- 适合:网站/H5/小程序/App 内置页多端发布;有 CDN;迭代频率较高;对灰度与回滚有要求。
- 不必上:一次性活动页、内部工具、用户量小且发布频率很低、团队暂时没有精力维护发布脚本。
边界可以这样理解:缓存策略的价值是让该更新的更新、该复用的复用。如果业务本身对版本不敏感,或者内容几乎不变,把精力投在四层核对上产出有限,按简化口径处理就行,不必为了统一而统一。
常见问题
本地看到新版,用户说没更新,第一步查什么?
先用无痕窗口和另一个网络环境各访问一次,两边都仍拿到旧版本,再去查 CDN 刷新记录和客户端缓存层。
入口 HTML 用协商缓存,会不会拖慢首屏?
影响有限。协商缓存命中 304 时传输量很小,按经验多在几十毫秒量级,通常小于资源体积差异带来的影响。
小程序发版后用户还是旧界面,也是缓存问题吗?
机制不同但相关。小程序有本地包与版本更新策略,往往需要用户重启或等待更新,可以在页面里放版本提示和手动更新入口。
静态资源不带内容指纹,只靠刷 CDN 行不行?
短期可行,长期容易返工。文件名不变时新旧文件同名,浏览器可能继续用旧副本,建议在构建阶段就带上内容指纹。
把「缓存头、资源哈希、CDN 刷新、客户端更新提示」写进发布清单,每次发版照单核对,通常比事后查问题省时间。如果项目只是单页静态站、没有 CDN 与离线缓存,按简化口径处理即可。上线后用无痕窗口和另一个网络环境各验一次,确认新版本真的到了用户侧。
-
2026年了,大模型流式对话点了停止还在吐字,是接口没断还是前端没收口?
日期:2026年9月15日 阅读:93
-
2026年了,需求评审都点头了,为什么联调时还在补空状态和加载态?
日期:2026年9月14日 阅读:80
-
Uni-app 同时发小程序和 App,平台差异越堆越多,2026 年从哪一步开始收?
日期:2026年9月12日 阅读:80
-
2026年了,Flutter 打出来的安装包偏大,是引擎的锅还是项目里塞多了东西?
日期:2026年9月11日 阅读:61
-
前端SEO(Google/百度)页面URL带#号,会影响收录吗?
日期:2026年9月10日 阅读:105




