[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"i-ri:search-line":3,"i-ri:moon-line":8,"i-ri:sun-line":10,"i-ri:menu-3-line":12,"i-ri:close-line":14,"notes-module-items-frontend":16,"notes-page-frontend-04-web-delivery\u002F01-cache-diagnosis":42,"i-ri:arrow-left-s-line":307,"i-ri:menu-2-line":309,"i-ri:arrow-right-s-line":311,"i-ep:copy-document":313},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"currentColor\" d=\"m18.031 16.617l4.283 4.282l-1.415 1.415l-4.282-4.283A8.96 8.96 0 0 1 11 20c-4.968 0-9-4.032-9-9s4.032-9 9-9s9 4.032 9 9a8.96 8.96 0 0 1-1.969 5.617m-2.006-.742A6.98 6.98 0 0 0 18 11c0-3.867-3.133-7-7-7s-7 3.133-7 7s3.133 7 7 7a6.98 6.98 0 0 0 4.875-1.975z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"currentColor\" d=\"M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2h.1A6.98 6.98 0 0 0 10 7m-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938A8 8 0 0 0 4 12\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":11},"\u003Cpath fill=\"currentColor\" d=\"M12 18a6 6 0 1 1 0-12a6 6 0 0 1 0 12m0-2a4 4 0 1 0 0-8a4 4 0 0 0 0 8M11 1h2v3h-2zm0 19h2v3h-2zM3.515 4.929l1.414-1.414L7.05 5.636L5.636 7.05zM16.95 18.364l1.414-1.414l2.121 2.121l-1.414 1.414zm2.121-14.85l1.414 1.415l-2.121 2.121l-1.414-1.414zM5.636 16.95l1.414 1.414l-2.121 2.121l-1.414-1.414zM23 11v2h-3v-2zM4 11v2H1v-2z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":13},"\u003Cpath fill=\"currentColor\" d=\"M3 4h18v2H3zm6 7h12v2H9zm-6 7h18v2H3z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":15},"\u003Cpath fill=\"currentColor\" d=\"m12 10.587l4.95-4.95l1.414 1.414l-4.95 4.95l4.95 4.95l-1.415 1.414l-4.95-4.95l-4.949 4.95l-1.414-1.415l4.95-4.95l-4.95-4.95L7.05 5.638z\"\u002F>",[17,22,26,30,34,38],{"path":18,"title":19,"meta":20},"\u002Fnotes\u002Ffrontend\u002F01-forms\u002F01-clear-semantics","表单清空后，旧数据为什么又回来了？",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},"2026-11-05T09:47:15.000Z",{"path":23,"title":24,"meta":25},"\u002Fnotes\u002Ffrontend\u002F01-forms\u002F02-async-persistence","保存请求回来时，文档已经变了",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":27,"title":28,"meta":29},"\u002Fnotes\u002Ffrontend\u002F02-canvas\u002F01-geometry-history","拖一下画布，为什么撤销回不去了？",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":31,"title":32,"meta":33},"\u002Fnotes\u002Ffrontend\u002F03-printing\u002F01-pagination-fonts","预览正常，PDF 为何多一页或缺字？",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":35,"title":36,"meta":37},"\u002Fnotes\u002Ffrontend\u002F04-web-delivery\u002F01-cache-diagnosis","API 更新了，博客页面为什么还是旧的？",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":39,"title":40,"meta":41},"\u002Fnotes\u002Ffrontend","前端与 Web 工程",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"id":43,"type":44,"sourcePath":45,"routePath":35,"path":35,"title":36,"description":46,"updatedAt":21,"meta":47,"body":56,"toc":301},"bm90ZTpub3Rlcy9mcm9udGVuZC8wNC13ZWItZGVsaXZlcnkvMDEtY2FjaGUtZGlhZ25vc2lzLm1k","note","notes\u002Ffrontend\u002F04-web-delivery\u002F01-cache-diagnosis.md","一次发布 11 篇文章后，内容 API 已经能查到新文章，博客列表却没有更新。给列表 URL 加一个新的查询参数，同一个页面又能显示全部内容。",{"id":43,"type":44,"sourcePath":45,"slug":48,"title":36,"updatedAt":21,"description":46,"tags":49,"date":53,"comment":54,"summary":55,"lastUpdated":21},"frontend\u002F04-web-delivery\u002F01-cache-diagnosis",[50,51,52],"全栈","缓存","故障复盘","2026-09-15",true,"同一个列表页，普通 URL 返回旧内容，加参数却能看到新文章。用响应正文和缓存头逐层定位，最后找到代理中的旧缓存。",{"type":57,"children":58},"root",[59,67,72,77,84,98,169,174,186,192,197,202,207,213,226,231,243,249,254,270,275,295],{"type":60,"tag":61,"props":62,"children":64},"element","h1",{"id":63},"api-更新了博客页面为什么还是旧的",[65],{"type":66,"value":36},"text",{"type":60,"tag":68,"props":69,"children":70},"p",{},[71],{"type":66,"value":46},{"type":60,"tag":68,"props":73,"children":74},{},[75],{"type":66,"value":76},"这个站点从内容 API 读取 Markdown 索引，再由 Nuxt 在服务端生成页面。API 与页面不是同一个缓存对象，检查到前者更新，并不能说明后者已经更新。",{"type":60,"tag":78,"props":79,"children":81},"h2",{"id":80},"加参数就正常能说明什么",[82],{"type":66,"value":83},"加参数就正常，能说明什么？",{"type":60,"tag":68,"props":85,"children":86},{},[87,89,96],{"type":66,"value":88},"普通 ",{"type":60,"tag":90,"props":91,"children":93},"code",{"className":92},[],[94],{"type":66,"value":95},"\u002Fposts",{"type":66,"value":97}," 的 HTML 缺少新文章，响应头仍带着旧缓存信息：",{"type":60,"tag":99,"props":100,"children":105},"pre",{"className":101,"code":102,"language":103,"meta":104,"style":104},"language-http shiki shiki-themes github-light github-dark","Cache-Control: s-maxage=3600, stale-while-revalidate\nX-Cache: HIT\nLast-Modified: \u003C旧时间>\n","http","",[106],{"type":60,"tag":90,"props":107,"children":108},{"__ignoreMap":104},[109,133,151],{"type":60,"tag":110,"props":111,"children":114},"span",{"class":112,"line":113},"line",1,[115,121,127],{"type":60,"tag":110,"props":116,"children":118},{"style":117},"--shiki-default:#22863A;--shiki-dark:#85E89D",[119],{"type":66,"value":120},"Cache-Control",{"type":60,"tag":110,"props":122,"children":124},{"style":123},"--shiki-default:#D73A49;--shiki-dark:#F97583",[125],{"type":66,"value":126},":",{"type":60,"tag":110,"props":128,"children":130},{"style":129},"--shiki-default:#032F62;--shiki-dark:#9ECBFF",[131],{"type":66,"value":132}," s-maxage=3600, stale-while-revalidate\n",{"type":60,"tag":110,"props":134,"children":136},{"class":112,"line":135},2,[137,142,146],{"type":60,"tag":110,"props":138,"children":139},{"style":117},[140],{"type":66,"value":141},"X-Cache",{"type":60,"tag":110,"props":143,"children":144},{"style":123},[145],{"type":66,"value":126},{"type":60,"tag":110,"props":147,"children":148},{"style":129},[149],{"type":66,"value":150}," HIT\n",{"type":60,"tag":110,"props":152,"children":154},{"class":112,"line":153},3,[155,160,164],{"type":60,"tag":110,"props":156,"children":157},{"style":117},[158],{"type":66,"value":159},"Last-Modified",{"type":60,"tag":110,"props":161,"children":162},{"style":123},[163],{"type":66,"value":126},{"type":60,"tag":110,"props":165,"children":166},{"style":129},[167],{"type":66,"value":168}," \u003C旧时间>\n",{"type":60,"tag":68,"props":170,"children":171},{},[172],{"type":66,"value":173},"新参数地址返回 MISS，HTML 中有全部新文章。两份响应的差异说明：应用有能力生成新页面，但普通地址仍在命中某份旧对象。",{"type":60,"tag":68,"props":175,"children":176},{},[177,179,184],{"type":66,"value":178},"还不能仅凭 ",{"type":60,"tag":90,"props":180,"children":182},{"className":181},[],[183],{"type":66,"value":141},{"type":66,"value":185}," 就确定是哪一层。应用数据缓存、整页缓存、反向代理和浏览器，都可能参与请求，需要把返回的正文与各层配置对起来。",{"type":60,"tag":78,"props":187,"children":189},{"id":188},"这种更新问题通常有哪些处理方式",[190],{"type":66,"value":191},"这种更新问题，通常有哪些处理方式？",{"type":60,"tag":68,"props":193,"children":194},{},[195],{"type":66,"value":196},"可以等待缓存过期、让发布流程主动失效相关对象，或者关闭不适合当前更新频率的缓存。选择取决于允许读者看到多旧的数据，以及愿意承担多少重新渲染开销。",{"type":60,"tag":68,"props":198,"children":199},{},[200],{"type":66,"value":201},"排查时先把链路列出来更有用：内容文件变成 API 索引与详情，页面再取数据生成 HTML，HTML 可能被上游代理保存，最后才到浏览器。最外层直接回旧 HTML 时，请求根本不会到达内容 API，重启 API 自然影响不到它。",{"type":60,"tag":68,"props":203,"children":204},{},[205],{"type":66,"value":206},"这次先调整应用层，再继续对照部署后的普通地址，没有把新参数能看到内容当作排查结束。",{"type":60,"tag":78,"props":208,"children":210},{"id":209},"应用改成-no-store为什么还没好",[211],{"type":66,"value":212},"应用改成 no-store，为什么还没好？",{"type":60,"tag":68,"props":214,"children":215},{},[216,218,224],{"type":66,"value":217},"站点先取消列表、标签和详情路由的整页 SWR，响应改成 ",{"type":60,"tag":90,"props":219,"children":221},{"className":220},[],[222],{"type":66,"value":223},"Cache-Control: no-store",{"type":66,"value":225},"。数据读取缓存仍保留：索引 60 秒，详情 10 分钟。这样页面重新进行服务端渲染，但底层数据还能短暂复用。",{"type":60,"tag":68,"props":227,"children":228},{},[229],{"type":66,"value":230},"代价是服务端渲染次数增加，详情仍可能读到十分钟前的数据，已打开页面也不会自动刷新。这是当时接受的更新与开销取舍。",{"type":60,"tag":68,"props":232,"children":233},{},[234,236,241],{"type":66,"value":235},"本地生产构建连接真实内容 API 时，新文章和新响应头都正常。部署后，新参数地址能拿到 no-store，普通 ",{"type":60,"tag":90,"props":237,"children":239},{"className":238},[],[240],{"type":66,"value":95},{"type":66,"value":242}," 却仍是 HIT 和旧正文。新的响应头没有清掉上游已经保存的旧对象，请求在到达新应用前就返回了。",{"type":60,"tag":78,"props":244,"children":246},{"id":245},"最后怎样确认是代理缓存",[247],{"type":66,"value":248},"最后怎样确认是代理缓存？",{"type":60,"tag":68,"props":250,"children":251},{},[252],{"type":66,"value":253},"检查目标站点代理时，面板缓存开关虽然关闭，配置中却没有显式禁用对应位置的缓存。补上下面这一行后，再访问普通地址：",{"type":60,"tag":99,"props":255,"children":259},{"className":256,"code":257,"language":258,"meta":104,"style":104},"language-nginx shiki shiki-themes github-light github-dark","proxy_cache off;\n","nginx",[260],{"type":60,"tag":90,"props":261,"children":262},{"__ignoreMap":104},[263],{"type":60,"tag":110,"props":264,"children":265},{"class":112,"line":113},[266],{"type":60,"tag":110,"props":267,"children":268},{},[269],{"type":66,"value":257},{"type":60,"tag":68,"props":271,"children":272},{},[273],{"type":66,"value":274},"旧 HIT 消失，HTML 中缺少的新文章数量从 11 变成 0。这次关闭的是目标位置对缓存的使用，没有物理删除服务器缓存目录，也没有继续追完所有配置继承来源。",{"type":60,"tag":68,"props":276,"children":277},{},[278,280,285,287,293],{"type":66,"value":279},"收尾仍检查读者平时访问的 ",{"type":60,"tag":90,"props":281,"children":283},{"className":282},[],[284],{"type":66,"value":95},{"type":66,"value":286},"、",{"type":60,"tag":90,"props":288,"children":290},{"className":289},[],[291],{"type":66,"value":292},"\u002Ftags",{"type":66,"value":294}," 和文章详情，对照状态码、缓存头及正文。带参数地址只用于比较，不能替代原 URL 的验收。本篇记录的是当时的处理过程，本次整理没有重新核查线上配置。",{"type":60,"tag":296,"props":297,"children":298},"style",{},[299],{"type":66,"value":300},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":104,"searchDepth":135,"depth":135,"links":302},[303,304,305,306],{"id":80,"depth":135,"text":83},{"id":188,"depth":135,"text":191},{"id":209,"depth":135,"text":212},{"id":245,"depth":135,"text":248},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":308},"\u003Cpath fill=\"currentColor\" d=\"m10.828 12l4.95 4.95l-1.414 1.415L8 12l6.364-6.364l1.414 1.414z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":310},"\u003Cpath fill=\"currentColor\" d=\"M3 4h18v2H3zm0 7h12v2H3zm0 7h18v2H3z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":312},"\u003Cpath fill=\"currentColor\" d=\"m13.172 12l-4.95-4.95l1.414-1.413L16 12l-6.364 6.364l-1.414-1.415z\"\u002F>",{"left":4,"top":4,"width":314,"height":314,"rotate":4,"vFlip":6,"hFlip":6,"body":315},1024,"\u003Cpath fill=\"currentColor\" d=\"M768 832a128 128 0 0 1-128 128H192A128 128 0 0 1 64 832V384a128 128 0 0 1 128-128v64a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64z\"\u002F>\u003Cpath fill=\"currentColor\" d=\"M384 128a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64V192a64 64 0 0 0-64-64zm0-64h448a128 128 0 0 1 128 128v448a128 128 0 0 1-128 128H384a128 128 0 0 1-128-128V192A128 128 0 0 1 384 64\"\u002F>"]