[{"data":1,"prerenderedAt":4212},["ShallowReactive",2],{"article-/topics/next/vercel-deployment-optimization-guide":3,"related-next":621,"content-query-3feRiGNGlr":3743},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"topic":5,"author":11,"tags":12,"image":18,"imageQuery":19,"pexelsPhotoId":20,"pexelsUrl":21,"featured":6,"readingTime":22,"body":23,"_type":615,"_id":616,"_source":617,"_file":618,"_stem":619,"_extension":620},"/topics/next/vercel-deployment-optimization-guide","next",false,"","Vercel 部署深度优化：构建、边缘函数与成本控制","从构建时间、环境变量、缓存策略、边缘函数、日志观测到成本治理，系统讲清 Next.js 项目部署到 Vercel 后如何真正跑稳、跑快、跑得起。","2026-04-06","HTMLPAGE 团队",[13,14,15,16,17],"Vercel","Next.js 部署","边缘函数","成本控制","性能优化","/images/topics/next/vercel-deployment-optimization-guide.jpg","cloud deployment monitoring dashboard laptop",577195,"https://www.pexels.com/photo/turned-on-laptop-computer-577195/",14,{"type":24,"children":25,"toc":597},"root",[26,35,41,46,71,77,82,175,180,186,191,209,214,233,239,244,262,267,285,290,296,301,319,324,329,347,353,358,363,381,386,392,397,420,425,431,512,518,525,530,536,541,547,552,557],{"type":27,"tag":28,"props":29,"children":31},"element","h2",{"id":30},"vercel-部署深度优化",[32],{"type":33,"value":34},"text","Vercel 部署深度优化",{"type":27,"tag":36,"props":37,"children":38},"p",{},[39],{"type":33,"value":40},"把 Next.js 项目推上 Vercel 很简单，真正难的是把它部署成一个稳定服务，而不是“偶尔能打开的线上演示”。",{"type":27,"tag":36,"props":42,"children":43},{},[44],{"type":33,"value":45},"团队常见的上线后问题基本集中在四类：",{"type":27,"tag":47,"props":48,"children":49},"ul",{},[50,56,61,66],{"type":27,"tag":51,"props":52,"children":53},"li",{},[54],{"type":33,"value":55},"构建越来越慢。",{"type":27,"tag":51,"props":57,"children":58},{},[59],{"type":33,"value":60},"环境变量和分支环境混乱。",{"type":27,"tag":51,"props":62,"children":63},{},[64],{"type":33,"value":65},"边缘函数和 Node 运行时边界不清。",{"type":27,"tag":51,"props":67,"children":68},{},[69],{"type":33,"value":70},"成本上涨但不知道是哪部分在烧钱。",{"type":27,"tag":28,"props":72,"children":74},{"id":73},"_1-vercel-优化的核心不是更多配置而是更清楚的运行边界",[75],{"type":33,"value":76},"1. Vercel 优化的核心不是“更多配置”，而是“更清楚的运行边界”",{"type":27,"tag":36,"props":78,"children":79},{},[80],{"type":33,"value":81},"你至少要明确这几件事：",{"type":27,"tag":83,"props":84,"children":85},"table",{},[86,105],{"type":27,"tag":87,"props":88,"children":89},"thead",{},[90],{"type":27,"tag":91,"props":92,"children":93},"tr",{},[94,100],{"type":27,"tag":95,"props":96,"children":97},"th",{},[98],{"type":33,"value":99},"维度",{"type":27,"tag":95,"props":101,"children":102},{},[103],{"type":33,"value":104},"需要回答的问题",{"type":27,"tag":106,"props":107,"children":108},"tbody",{},[109,123,136,149,162],{"type":27,"tag":91,"props":110,"children":111},{},[112,118],{"type":27,"tag":113,"props":114,"children":115},"td",{},[116],{"type":33,"value":117},"构建",{"type":27,"tag":113,"props":119,"children":120},{},[121],{"type":33,"value":122},"为什么这次构建比上次更慢？",{"type":27,"tag":91,"props":124,"children":125},{},[126,131],{"type":27,"tag":113,"props":127,"children":128},{},[129],{"type":33,"value":130},"运行时",{"type":27,"tag":113,"props":132,"children":133},{},[134],{"type":33,"value":135},"这个路由适合 Edge 还是 Node？",{"type":27,"tag":91,"props":137,"children":138},{},[139,144],{"type":27,"tag":113,"props":140,"children":141},{},[142],{"type":33,"value":143},"缓存",{"type":27,"tag":113,"props":145,"children":146},{},[147],{"type":33,"value":148},"数据和页面分别缓存多久？",{"type":27,"tag":91,"props":150,"children":151},{},[152,157],{"type":27,"tag":113,"props":153,"children":154},{},[155],{"type":33,"value":156},"环境",{"type":27,"tag":113,"props":158,"children":159},{},[160],{"type":33,"value":161},"Preview、Production 是否隔离？",{"type":27,"tag":91,"props":163,"children":164},{},[165,170],{"type":27,"tag":113,"props":166,"children":167},{},[168],{"type":33,"value":169},"成本",{"type":27,"tag":113,"props":171,"children":172},{},[173],{"type":33,"value":174},"是构建费、函数费还是带宽费在涨？",{"type":27,"tag":36,"props":176,"children":177},{},[178],{"type":33,"value":179},"只要这些边界没定义清楚，优化就会变成盲调。",{"type":27,"tag":28,"props":181,"children":183},{"id":182},"_2-构建时间变慢通常不是-vercel-的锅而是项目边界膨胀了",[184],{"type":33,"value":185},"2. 构建时间变慢，通常不是 Vercel 的锅，而是项目边界膨胀了",{"type":27,"tag":36,"props":187,"children":188},{},[189],{"type":33,"value":190},"最常见的构建变慢原因包括：",{"type":27,"tag":47,"props":192,"children":193},{},[194,199,204],{"type":27,"tag":51,"props":195,"children":196},{},[197],{"type":33,"value":198},"不必要的大依赖进入服务端 bundle。",{"type":27,"tag":51,"props":200,"children":201},{},[202],{"type":33,"value":203},"图片和内容处理在构建期做太多。",{"type":27,"tag":51,"props":205,"children":206},{},[207],{"type":33,"value":208},"monorepo 里没有按影响范围构建。",{"type":27,"tag":36,"props":210,"children":211},{},[212],{"type":33,"value":213},"更稳的做法是：",{"type":27,"tag":215,"props":216,"children":217},"ol",{},[218,223,228],{"type":27,"tag":51,"props":219,"children":220},{},[221],{"type":33,"value":222},"把大而少变的内容移出构建主链。",{"type":27,"tag":51,"props":224,"children":225},{},[226],{"type":33,"value":227},"精简 server-only 与 client-only 依赖。",{"type":27,"tag":51,"props":229,"children":230},{},[231],{"type":33,"value":232},"在 monorepo 中明确 filter 和缓存策略。",{"type":27,"tag":28,"props":234,"children":236},{"id":235},"_3-edge-runtime-很强但不是所有逻辑都该上-edge",[237],{"type":33,"value":238},"3. Edge Runtime 很强，但不是所有逻辑都该上 Edge",{"type":27,"tag":36,"props":240,"children":241},{},[242],{"type":33,"value":243},"Edge 更适合：",{"type":27,"tag":47,"props":245,"children":246},{},[247,252,257],{"type":27,"tag":51,"props":248,"children":249},{},[250],{"type":33,"value":251},"全球就近响应。",{"type":27,"tag":51,"props":253,"children":254},{},[255],{"type":33,"value":256},"轻量鉴权与路由决策。",{"type":27,"tag":51,"props":258,"children":259},{},[260],{"type":33,"value":261},"简单个性化输出。",{"type":27,"tag":36,"props":263,"children":264},{},[265],{"type":33,"value":266},"不适合：",{"type":27,"tag":47,"props":268,"children":269},{},[270,275,280],{"type":27,"tag":51,"props":271,"children":272},{},[273],{"type":33,"value":274},"强依赖 Node API 的逻辑。",{"type":27,"tag":51,"props":276,"children":277},{},[278],{"type":33,"value":279},"大量数据库驱动和复杂计算。",{"type":27,"tag":51,"props":281,"children":282},{},[283],{"type":33,"value":284},"长时间执行任务。",{"type":27,"tag":36,"props":286,"children":287},{},[288],{"type":33,"value":289},"错误做法是“为了快就全部上 Edge”，最后调试复杂度和兼容问题一起上升。",{"type":27,"tag":28,"props":291,"children":293},{"id":292},"_4-一个常见失败案例预发环境和生产共用配置结果发布成功但功能异常",[294],{"type":33,"value":295},"4. 一个常见失败案例：预发环境和生产共用配置，结果发布成功但功能异常",{"type":27,"tag":36,"props":297,"children":298},{},[299],{"type":33,"value":300},"这类问题很高发：",{"type":27,"tag":215,"props":302,"children":303},{},[304,309,314],{"type":27,"tag":51,"props":305,"children":306},{},[307],{"type":33,"value":308},"Preview 与 Production 用了同一套外部服务配置。",{"type":27,"tag":51,"props":310,"children":311},{},[312],{"type":33,"value":313},"预发数据误写到生产库。",{"type":27,"tag":51,"props":315,"children":316},{},[317],{"type":33,"value":318},"发布时页面能打开，但真实业务已被污染。",{"type":27,"tag":36,"props":320,"children":321},{},[322],{"type":33,"value":323},"根因不是 Vercel 配置复杂，而是环境边界没有被当成产品边界管理。",{"type":27,"tag":36,"props":325,"children":326},{},[327],{"type":33,"value":328},"修复方式通常是：",{"type":27,"tag":215,"props":330,"children":331},{},[332,337,342],{"type":27,"tag":51,"props":333,"children":334},{},[335],{"type":33,"value":336},"明确区分 preview/prod 环境变量。",{"type":27,"tag":51,"props":338,"children":339},{},[340],{"type":33,"value":341},"外部服务按环境分实例或分 schema。",{"type":27,"tag":51,"props":343,"children":344},{},[345],{"type":33,"value":346},"发布前检查关键环境变量来源。",{"type":27,"tag":28,"props":348,"children":350},{"id":349},"_5-成本治理要拆成构建函数和带宽三张账",[351],{"type":33,"value":352},"5. 成本治理要拆成构建、函数和带宽三张账",{"type":27,"tag":36,"props":354,"children":355},{},[356],{"type":33,"value":357},"很多团队只看到总账单，不知道哪里有问题。",{"type":27,"tag":36,"props":359,"children":360},{},[361],{"type":33,"value":362},"更实用的拆法是：",{"type":27,"tag":47,"props":364,"children":365},{},[366,371,376],{"type":27,"tag":51,"props":367,"children":368},{},[369],{"type":33,"value":370},"构建成本：构建次数、构建时长、缓存命中率。",{"type":27,"tag":51,"props":372,"children":373},{},[374],{"type":33,"value":375},"函数成本：调用次数、平均执行时长、冷启动情况。",{"type":27,"tag":51,"props":377,"children":378},{},[379],{"type":33,"value":380},"带宽成本：图片、脚本、文件下载流量。",{"type":27,"tag":36,"props":382,"children":383},{},[384],{"type":33,"value":385},"只有拆开看，你才知道是该优化 bundle，还是该优化函数调用频率。",{"type":27,"tag":28,"props":387,"children":389},{"id":388},"_6-观测要覆盖发布后是否真的变好而不是只看构建成功",[390],{"type":33,"value":391},"6. 观测要覆盖“发布后是否真的变好”，而不是只看构建成功",{"type":27,"tag":36,"props":393,"children":394},{},[395],{"type":33,"value":396},"至少要盯这几类信号：",{"type":27,"tag":47,"props":398,"children":399},{},[400,405,410,415],{"type":27,"tag":51,"props":401,"children":402},{},[403],{"type":33,"value":404},"发布后错误率。",{"type":27,"tag":51,"props":406,"children":407},{},[408],{"type":33,"value":409},"关键页面 TTFB 和 LCP。",{"type":27,"tag":51,"props":411,"children":412},{},[413],{"type":33,"value":414},"函数超时和重试。",{"type":27,"tag":51,"props":416,"children":417},{},[418],{"type":33,"value":419},"环境变量缺失或配置异常。",{"type":27,"tag":36,"props":421,"children":422},{},[423],{"type":33,"value":424},"“Deployment successful” 只是开始，不是验证结束。",{"type":27,"tag":28,"props":426,"children":428},{"id":427},"_7-上线前-checklist",[429],{"type":33,"value":430},"7. 上线前 Checklist",{"type":27,"tag":47,"props":432,"children":435},{"className":433},[434],"contains-task-list",[436,449,458,467,476,485,494,503],{"type":27,"tag":51,"props":437,"children":440},{"className":438},[439],"task-list-item",[441,447],{"type":27,"tag":442,"props":443,"children":446},"input",{"disabled":444,"type":445},true,"checkbox",[],{"type":33,"value":448}," 已区分 Preview 与 Production 环境变量。",{"type":27,"tag":51,"props":450,"children":452},{"className":451},[439],[453,456],{"type":27,"tag":442,"props":454,"children":455},{"disabled":444,"type":445},[],{"type":33,"value":457}," 已确认哪些路由适合 Edge，哪些保留 Node。",{"type":27,"tag":51,"props":459,"children":461},{"className":460},[439],[462,465],{"type":27,"tag":442,"props":463,"children":464},{"disabled":444,"type":445},[],{"type":33,"value":466}," 构建链路中没有不必要的大依赖和重处理。",{"type":27,"tag":51,"props":468,"children":470},{"className":469},[439],[471,474],{"type":27,"tag":442,"props":472,"children":473},{"disabled":444,"type":445},[],{"type":33,"value":475}," 已监控函数耗时、错误率与超时。",{"type":27,"tag":51,"props":477,"children":479},{"className":478},[439],[480,483],{"type":27,"tag":442,"props":481,"children":482},{"disabled":444,"type":445},[],{"type":33,"value":484}," 已拆出构建、函数、带宽三类成本口径。",{"type":27,"tag":51,"props":486,"children":488},{"className":487},[439],[489,492],{"type":27,"tag":442,"props":490,"children":491},{"disabled":444,"type":445},[],{"type":33,"value":493}," 发布后有真实页面与关键流程回归检查。",{"type":27,"tag":51,"props":495,"children":497},{"className":496},[439],[498,501],{"type":27,"tag":442,"props":499,"children":500},{"disabled":444,"type":445},[],{"type":33,"value":502}," 已准备出错时的快速回滚路径。",{"type":27,"tag":51,"props":504,"children":506},{"className":505},[439],[507,510],{"type":27,"tag":442,"props":508,"children":509},{"disabled":444,"type":445},[],{"type":33,"value":511}," 关键外部服务的环境边界已验证。",{"type":27,"tag":28,"props":513,"children":515},{"id":514},"faq",[516],{"type":33,"value":517},"FAQ",{"type":27,"tag":519,"props":520,"children":522},"h3",{"id":521},"上-vercel-后性能一定会变好吗",[523],{"type":33,"value":524},"上 Vercel 后性能一定会变好吗？",{"type":27,"tag":36,"props":526,"children":527},{},[528],{"type":33,"value":529},"不一定。平台提供了能力，但页面快不快，仍然取决于你的渲染策略、资源体积和缓存设计。",{"type":27,"tag":519,"props":531,"children":533},{"id":532},"什么场景适合-edge-runtime",[534],{"type":33,"value":535},"什么场景适合 Edge Runtime？",{"type":27,"tag":36,"props":537,"children":538},{},[539],{"type":33,"value":540},"更适合轻逻辑、低延迟和全球访问场景，不适合重数据库逻辑和复杂 Node 依赖。",{"type":27,"tag":519,"props":542,"children":544},{"id":543},"如何快速判断成本问题在哪",[545],{"type":33,"value":546},"如何快速判断成本问题在哪？",{"type":27,"tag":36,"props":548,"children":549},{},[550],{"type":33,"value":551},"先拆账单来源，再对照构建时长、函数调用量和资源流量，不要只看总额。",{"type":27,"tag":28,"props":553,"children":555},{"id":554},"延伸阅读",[556],{"type":33,"value":554},{"type":27,"tag":47,"props":558,"children":559},{},[560,570,579,588],{"type":27,"tag":51,"props":561,"children":562},{},[563],{"type":27,"tag":564,"props":565,"children":567},"a",{"href":566},"/topics/next/nextjs-15-features-rsc-guide",[568],{"type":33,"value":569},"Next.js 15 新特性全解析：Turbopack 稳定版与 React Server Components 深度实践",{"type":27,"tag":51,"props":571,"children":572},{},[573],{"type":27,"tag":564,"props":574,"children":576},{"href":575},"/topics/next/nextjs-fullstack-saas-guide",[577],{"type":33,"value":578},"构建全栈 SaaS 应用：Next.js 从认证到计费的产品化落地指南",{"type":27,"tag":51,"props":580,"children":581},{},[582],{"type":27,"tag":564,"props":583,"children":585},{"href":584},"/topics/next/nextjs-supabase-practical-guide",[586],{"type":33,"value":587},"Next.js + Supabase 实战：认证、数据库与实时能力怎么接",{"type":27,"tag":51,"props":589,"children":590},{},[591],{"type":27,"tag":564,"props":592,"children":594},{"href":593},"/topics/next/cache-strategy-deep-dive",[595],{"type":33,"value":596},"缓存策略深度解析：Next.js App Router 下的数据与页面缓存",{"title":7,"searchDepth":598,"depth":598,"links":599},3,[600,602,603,604,605,606,607,608,609,614],{"id":30,"depth":601,"text":34},2,{"id":73,"depth":601,"text":76},{"id":182,"depth":601,"text":185},{"id":235,"depth":601,"text":238},{"id":292,"depth":601,"text":295},{"id":349,"depth":601,"text":352},{"id":388,"depth":601,"text":391},{"id":427,"depth":601,"text":430},{"id":514,"depth":601,"text":517,"children":610},[611,612,613],{"id":521,"depth":598,"text":524},{"id":532,"depth":598,"text":535},{"id":543,"depth":598,"text":546},{"id":554,"depth":601,"text":554},"markdown","content:topics:next:vercel-deployment-optimization-guide.md","content","topics/next/vercel-deployment-optimization-guide.md","topics/next/vercel-deployment-optimization-guide","md",[622,1807,2617],{"_path":593,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":623,"description":624,"date":625,"topic":5,"author":11,"tags":626,"image":632,"featured":444,"readingTime":633,"body":634,"_type":615,"_id":1804,"_source":617,"_file":1805,"_stem":1806,"_extension":620},"缓存策略深度解析","从 HTTP/CDN 到 Next.js App Router 的缓存语义，系统拆解缓存的分层模型、失效策略与常见踩坑，给出可直接落地的工程化方案与检查清单。","2026-01-20",[143,627,628,629,630,631],"CDN","Next.js","App Router","revalidateTag","Cache-Control","/images/topics/next/cache-strategy.jpg",22,{"type":24,"children":635,"toc":1770},[636,640,653,658,676,681,699,704,708,714,719,762,767,785,791,804,809,812,818,823,888,894,899,911,916,934,940,945,964,974,977,983,988,1001,1006,1012,1017,1082,1095,1101,1106,1133,1136,1142,1147,1170,1176,1181,1199,1204,1210,1235,1240,1253,1256,1262,1267,1285,1291,1296,1326,1331,1356,1361,1367,1378,1396,1399,1405,1411,1429,1435,1453,1458,1471,1474,1480,1485,1513,1518,1547,1550,1556,1562,1600,1606,1648,1654,1672,1675,1681,1739,1742,1747,1752],{"type":27,"tag":28,"props":637,"children":638},{"id":623},[639],{"type":33,"value":623},{"type":27,"tag":36,"props":641,"children":642},{},[643,645,651],{"type":33,"value":644},"缓存不是“开关”，而是一套",{"type":27,"tag":646,"props":647,"children":648},"strong",{},[649],{"type":33,"value":650},"分层一致性工程",{"type":33,"value":652},"。",{"type":27,"tag":36,"props":654,"children":655},{},[656],{"type":33,"value":657},"做得好，缓存能同时提升：",{"type":27,"tag":47,"props":659,"children":660},{},[661,666,671],{"type":27,"tag":51,"props":662,"children":663},{},[664],{"type":33,"value":665},"TTFB / LCP（更快）",{"type":27,"tag":51,"props":667,"children":668},{},[669],{"type":33,"value":670},"稳定性（抗突发流量、抗抖动）",{"type":27,"tag":51,"props":672,"children":673},{},[674],{"type":33,"value":675},"成本（更少的源站请求）",{"type":27,"tag":36,"props":677,"children":678},{},[679],{"type":33,"value":680},"做得不好，缓存会制造更可怕的问题：",{"type":27,"tag":47,"props":682,"children":683},{},[684,689,694],{"type":27,"tag":51,"props":685,"children":686},{},[687],{"type":33,"value":688},"用户看到过期数据，且你无法复现",{"type":27,"tag":51,"props":690,"children":691},{},[692],{"type":33,"value":693},"A 用户的内容被 B 用户读到（严重安全事故）",{"type":27,"tag":51,"props":695,"children":696},{},[697],{"type":33,"value":698},"缓存命中率很低，反而更慢、更贵",{"type":27,"tag":36,"props":700,"children":701},{},[702],{"type":33,"value":703},"这篇文章的目标是：让你用一套统一的心智模型，设计并落地“可控、可观测、可回滚”的缓存系统。并以 Next.js App Router 为例，把框架缓存语义纳入整套设计。",{"type":27,"tag":705,"props":706,"children":707},"hr",{},[],{"type":27,"tag":28,"props":709,"children":711},{"id":710},"_1-先建立缓存的分层模型",[712],{"type":33,"value":713},"1. 先建立缓存的“分层模型”",{"type":27,"tag":36,"props":715,"children":716},{},[717],{"type":33,"value":718},"真实系统的缓存几乎总是分层的：",{"type":27,"tag":215,"props":720,"children":721},{},[722,732,742,752],{"type":27,"tag":51,"props":723,"children":724},{},[725,730],{"type":27,"tag":646,"props":726,"children":727},{},[728],{"type":33,"value":729},"浏览器缓存",{"type":33,"value":731},"（Browser Cache）",{"type":27,"tag":51,"props":733,"children":734},{},[735,740],{"type":27,"tag":646,"props":736,"children":737},{},[738],{"type":33,"value":739},"CDN/边缘缓存",{"type":33,"value":741},"（Edge Cache）",{"type":27,"tag":51,"props":743,"children":744},{},[745,750],{"type":27,"tag":646,"props":746,"children":747},{},[748],{"type":33,"value":749},"应用侧缓存",{"type":33,"value":751},"（App Cache：SSR/RSC payload、fetch cache）",{"type":27,"tag":51,"props":753,"children":754},{},[755,760],{"type":27,"tag":646,"props":756,"children":757},{},[758],{"type":33,"value":759},"数据侧缓存",{"type":33,"value":761},"（Redis/DB buffer）",{"type":27,"tag":36,"props":763,"children":764},{},[765],{"type":33,"value":766},"你需要明确：",{"type":27,"tag":47,"props":768,"children":769},{},[770,775,780],{"type":27,"tag":51,"props":771,"children":772},{},[773],{"type":33,"value":774},"每一层缓存什么？（HTML / JSON / 静态资源 / RSC payload）",{"type":27,"tag":51,"props":776,"children":777},{},[778],{"type":33,"value":779},"每一层的 TTL 多久？",{"type":27,"tag":51,"props":781,"children":782},{},[783],{"type":33,"value":784},"写操作发生后，哪几层需要失效？",{"type":27,"tag":519,"props":786,"children":788},{"id":787},"_11-缓存的两类问题性能与一致性",[789],{"type":33,"value":790},"1.1 缓存的两类问题：性能与一致性",{"type":27,"tag":47,"props":792,"children":793},{},[794,799],{"type":27,"tag":51,"props":795,"children":796},{},[797],{"type":33,"value":798},"性能问题：命中率、压缩、复用、减少源站",{"type":27,"tag":51,"props":800,"children":801},{},[802],{"type":33,"value":803},"一致性问题：失效、隔离、权限、版本",{"type":27,"tag":36,"props":805,"children":806},{},[807],{"type":33,"value":808},"很多团队“缓存做不好”，本质是只解决了性能，忽略了一致性。",{"type":27,"tag":705,"props":810,"children":811},{},[],{"type":27,"tag":28,"props":813,"children":815},{"id":814},"_2-http-缓存基础cache-control-的正确用法",[816],{"type":33,"value":817},"2. HTTP 缓存基础：Cache-Control 的正确用法",{"type":27,"tag":36,"props":819,"children":820},{},[821],{"type":33,"value":822},"HTTP 缓存是地基。你至少要掌握这些指令：",{"type":27,"tag":47,"props":824,"children":825},{},[826,844,855,866,877],{"type":27,"tag":51,"props":827,"children":828},{},[829,836,838],{"type":27,"tag":830,"props":831,"children":833},"code",{"className":832},[],[834],{"type":33,"value":835},"public",{"type":33,"value":837}," / ",{"type":27,"tag":830,"props":839,"children":841},{"className":840},[],[842],{"type":33,"value":843},"private",{"type":27,"tag":51,"props":845,"children":846},{},[847,853],{"type":27,"tag":830,"props":848,"children":850},{"className":849},[],[851],{"type":33,"value":852},"max-age",{"type":33,"value":854},"（强缓存 TTL）",{"type":27,"tag":51,"props":856,"children":857},{},[858,864],{"type":27,"tag":830,"props":859,"children":861},{"className":860},[],[862],{"type":33,"value":863},"s-maxage",{"type":33,"value":865},"（CDN 侧 TTL）",{"type":27,"tag":51,"props":867,"children":868},{},[869,875],{"type":27,"tag":830,"props":870,"children":872},{"className":871},[],[873],{"type":33,"value":874},"stale-while-revalidate",{"type":33,"value":876},"（过期可先用旧的，再后台更新）",{"type":27,"tag":51,"props":878,"children":879},{},[880,886],{"type":27,"tag":830,"props":881,"children":883},{"className":882},[],[884],{"type":33,"value":885},"no-store",{"type":33,"value":887},"（不要存储）",{"type":27,"tag":519,"props":889,"children":891},{"id":890},"_21-一个常用的-cdn-缓存头模板",[892],{"type":33,"value":893},"2.1 一个常用的 CDN 缓存头模板",{"type":27,"tag":36,"props":895,"children":896},{},[897],{"type":33,"value":898},"对“公共页面（无用户态）”：",{"type":27,"tag":900,"props":901,"children":906},"pre",{"className":902,"code":904,"language":905,"meta":7},[903],"language-http","Cache-Control: public, max-age=0, s-maxage=600, stale-while-revalidate=86400\n","http",[907],{"type":27,"tag":830,"props":908,"children":909},{"__ignoreMap":7},[910],{"type":33,"value":904},{"type":27,"tag":36,"props":912,"children":913},{},[914],{"type":33,"value":915},"含义：",{"type":27,"tag":47,"props":917,"children":918},{},[919,924,929],{"type":27,"tag":51,"props":920,"children":921},{},[922],{"type":33,"value":923},"浏览器不强缓存（max-age=0）",{"type":27,"tag":51,"props":925,"children":926},{},[927],{"type":33,"value":928},"CDN 缓存 10 分钟",{"type":27,"tag":51,"props":930,"children":931},{},[932],{"type":33,"value":933},"CDN 过期后仍可先用旧内容 1 天，同时异步更新",{"type":27,"tag":519,"props":935,"children":937},{"id":936},"_22-用户态页面默认-private-或-no-store",[938],{"type":33,"value":939},"2.2 用户态页面：默认 private 或 no-store",{"type":27,"tag":36,"props":941,"children":942},{},[943],{"type":33,"value":944},"一旦响应与用户身份有关：",{"type":27,"tag":47,"props":946,"children":947},{},[948,959],{"type":27,"tag":51,"props":949,"children":950},{},[951,953],{"type":33,"value":952},"默认：",{"type":27,"tag":830,"props":954,"children":956},{"className":955},[],[957],{"type":33,"value":958},"Cache-Control: private, no-store",{"type":27,"tag":51,"props":960,"children":961},{},[962],{"type":33,"value":963},"必须缓存时：缓存 key 必须包含用户维度（例如 userId/session）且只在应用侧缓存",{"type":27,"tag":36,"props":965,"children":966},{},[967,969],{"type":33,"value":968},"结论：",{"type":27,"tag":646,"props":970,"children":971},{},[972],{"type":33,"value":973},"宁可慢一点，也不要把用户态响应交给 CDN 缓存。",{"type":27,"tag":705,"props":975,"children":976},{},[],{"type":27,"tag":28,"props":978,"children":980},{"id":979},"_3-cdn-缓存命中率与-key-设计",[981],{"type":33,"value":982},"3. CDN 缓存：命中率与 Key 设计",{"type":27,"tag":36,"props":984,"children":985},{},[986],{"type":33,"value":987},"CDN 缓存的核心是：",{"type":27,"tag":47,"props":989,"children":990},{},[991,996],{"type":27,"tag":51,"props":992,"children":993},{},[994],{"type":33,"value":995},"你希望命中（hit），就要让相同内容的请求尽可能“看起来一样”",{"type":27,"tag":51,"props":997,"children":998},{},[999],{"type":33,"value":1000},"你希望隔离（safe），就要让不同内容的请求“必须不一样”",{"type":27,"tag":36,"props":1002,"children":1003},{},[1004],{"type":33,"value":1005},"这两个目标天然冲突。",{"type":27,"tag":519,"props":1007,"children":1009},{"id":1008},"_31-cache-key-里哪些维度必须考虑",[1010],{"type":33,"value":1011},"3.1 Cache Key 里哪些维度必须考虑？",{"type":27,"tag":36,"props":1013,"children":1014},{},[1015],{"type":33,"value":1016},"最常见维度：",{"type":27,"tag":47,"props":1018,"children":1019},{},[1020,1029,1038,1049,1060,1071],{"type":27,"tag":51,"props":1021,"children":1022},{},[1023],{"type":27,"tag":830,"props":1024,"children":1026},{"className":1025},[],[1027],{"type":33,"value":1028},"host",{"type":27,"tag":51,"props":1030,"children":1031},{},[1032],{"type":27,"tag":830,"props":1033,"children":1035},{"className":1034},[],[1036],{"type":33,"value":1037},"path",{"type":27,"tag":51,"props":1039,"children":1040},{},[1041,1047],{"type":27,"tag":830,"props":1042,"children":1044},{"className":1043},[],[1045],{"type":33,"value":1046},"query",{"type":33,"value":1048},"（是否纳入 key？）",{"type":27,"tag":51,"props":1050,"children":1051},{},[1052,1058],{"type":27,"tag":830,"props":1053,"children":1055},{"className":1054},[],[1056],{"type":33,"value":1057},"accept-encoding",{"type":33,"value":1059},"（gzip/br）",{"type":27,"tag":51,"props":1061,"children":1062},{},[1063,1069],{"type":27,"tag":830,"props":1064,"children":1066},{"className":1065},[],[1067],{"type":33,"value":1068},"accept-language",{"type":33,"value":1070},"（多语言站点）",{"type":27,"tag":51,"props":1072,"children":1073},{},[1074,1080],{"type":27,"tag":830,"props":1075,"children":1077},{"className":1076},[],[1078],{"type":33,"value":1079},"device",{"type":33,"value":1081},"（移动/桌面，如果你做了 UA vary）",{"type":27,"tag":36,"props":1083,"children":1084},{},[1085,1087,1093],{"type":33,"value":1086},"反例：把“跟内容无关的 query”放进 key（例如 ",{"type":27,"tag":830,"props":1088,"children":1090},{"className":1089},[],[1091],{"type":33,"value":1092},"utm_*",{"type":33,"value":1094},"），会把命中率直接打碎。",{"type":27,"tag":519,"props":1096,"children":1098},{"id":1097},"_32-解决-utm-污染规范化-url",[1099],{"type":33,"value":1100},"3.2 解决 UTM 污染：规范化 URL",{"type":27,"tag":36,"props":1102,"children":1103},{},[1104],{"type":33,"value":1105},"建议：",{"type":27,"tag":47,"props":1107,"children":1108},{},[1109,1121],{"type":27,"tag":51,"props":1110,"children":1111},{},[1112,1114,1119],{"type":33,"value":1113},"进入应用时把 ",{"type":27,"tag":830,"props":1115,"children":1117},{"className":1116},[],[1118],{"type":33,"value":1092},{"type":33,"value":1120}," 归一化并 301 到干净 URL",{"type":27,"tag":51,"props":1122,"children":1123},{},[1124,1126,1131],{"type":33,"value":1125},"或在 CDN 层将 ",{"type":27,"tag":830,"props":1127,"children":1129},{"className":1128},[],[1130],{"type":33,"value":1092},{"type":33,"value":1132}," 从 cache key 里剔除",{"type":27,"tag":705,"props":1134,"children":1135},{},[],{"type":27,"tag":28,"props":1137,"children":1139},{"id":1138},"_4-应用侧缓存nextjs-app-router-的缓存语义",[1140],{"type":33,"value":1141},"4. 应用侧缓存：Next.js App Router 的缓存语义",{"type":27,"tag":36,"props":1143,"children":1144},{},[1145],{"type":33,"value":1146},"App Router 的“缓存”不是一个地方，而是一套语义：",{"type":27,"tag":47,"props":1148,"children":1149},{},[1150,1155,1160,1165],{"type":27,"tag":51,"props":1151,"children":1152},{},[1153],{"type":33,"value":1154},"fetch 结果缓存",{"type":27,"tag":51,"props":1156,"children":1157},{},[1158],{"type":33,"value":1159},"RSC payload 缓存",{"type":27,"tag":51,"props":1161,"children":1162},{},[1163],{"type":33,"value":1164},"route segment 缓存",{"type":27,"tag":51,"props":1166,"children":1167},{},[1168],{"type":33,"value":1169},"revalidate 机制（path/tag）",{"type":27,"tag":519,"props":1171,"children":1173},{"id":1172},"_41-你必须区分静态动态按需再验证",[1174],{"type":33,"value":1175},"4.1 你必须区分：静态、动态、按需再验证",{"type":27,"tag":36,"props":1177,"children":1178},{},[1179],{"type":33,"value":1180},"在 App Router 体系里，一个页面/段可以是：",{"type":27,"tag":47,"props":1182,"children":1183},{},[1184,1189,1194],{"type":27,"tag":51,"props":1185,"children":1186},{},[1187],{"type":33,"value":1188},"静态（长 TTL）",{"type":27,"tag":51,"props":1190,"children":1191},{},[1192],{"type":33,"value":1193},"动态（每次都算）",{"type":27,"tag":51,"props":1195,"children":1196},{},[1197],{"type":33,"value":1198},"ISR/按需再验证（写操作后失效）",{"type":27,"tag":36,"props":1200,"children":1201},{},[1202],{"type":33,"value":1203},"不要把“页面慢”简单归因给 SSR；很多时候是缓存策略没设计好。",{"type":27,"tag":519,"props":1205,"children":1207},{"id":1206},"_42-两个最重要的失效-apirevalidatepath-revalidatetag",[1208],{"type":33,"value":1209},"4.2 两个最重要的失效 API：revalidatePath / revalidateTag",{"type":27,"tag":47,"props":1211,"children":1212},{},[1213,1224],{"type":27,"tag":51,"props":1214,"children":1215},{},[1216,1222],{"type":27,"tag":830,"props":1217,"children":1219},{"className":1218},[],[1220],{"type":33,"value":1221},"revalidatePath('/xxx')",{"type":33,"value":1223},"：按路由失效（粗粒度）",{"type":27,"tag":51,"props":1225,"children":1226},{},[1227,1233],{"type":27,"tag":830,"props":1228,"children":1230},{"className":1229},[],[1231],{"type":33,"value":1232},"revalidateTag('tag')",{"type":33,"value":1234},"：按数据域失效（细粒度）",{"type":27,"tag":36,"props":1236,"children":1237},{},[1238],{"type":33,"value":1239},"经验法则：",{"type":27,"tag":47,"props":1241,"children":1242},{},[1243,1248],{"type":27,"tag":51,"props":1244,"children":1245},{},[1246],{"type":33,"value":1247},"数据只影响单页：用 path",{"type":27,"tag":51,"props":1249,"children":1250},{},[1251],{"type":33,"value":1252},"数据影响多页（列表、详情、侧栏统计）：用 tag",{"type":27,"tag":705,"props":1254,"children":1255},{},[],{"type":27,"tag":28,"props":1257,"children":1259},{"id":1258},"_5-写操作后的失效策略从拍脑袋到可证明",[1260],{"type":33,"value":1261},"5. 写操作后的失效策略：从“拍脑袋”到“可证明”",{"type":27,"tag":36,"props":1263,"children":1264},{},[1265],{"type":33,"value":1266},"写操作发生后，你要回答：",{"type":27,"tag":47,"props":1268,"children":1269},{},[1270,1275,1280],{"type":27,"tag":51,"props":1271,"children":1272},{},[1273],{"type":33,"value":1274},"哪些页面会受影响？",{"type":27,"tag":51,"props":1276,"children":1277},{},[1278],{"type":33,"value":1279},"哪些数据域会受影响？",{"type":27,"tag":51,"props":1281,"children":1282},{},[1283],{"type":33,"value":1284},"这些受影响对象是否有统一 tag？",{"type":27,"tag":519,"props":1286,"children":1288},{"id":1287},"_51-建议采用域驱动-tag",[1289],{"type":33,"value":1290},"5.1 建议采用“域驱动 tag”",{"type":27,"tag":36,"props":1292,"children":1293},{},[1294],{"type":33,"value":1295},"例子：电商商品",{"type":27,"tag":47,"props":1297,"children":1298},{},[1299,1308,1317],{"type":27,"tag":51,"props":1300,"children":1301},{},[1302],{"type":27,"tag":830,"props":1303,"children":1305},{"className":1304},[],[1306],{"type":33,"value":1307},"product:{id}",{"type":27,"tag":51,"props":1309,"children":1310},{},[1311],{"type":27,"tag":830,"props":1312,"children":1314},{"className":1313},[],[1315],{"type":33,"value":1316},"product:list",{"type":27,"tag":51,"props":1318,"children":1319},{},[1320],{"type":27,"tag":830,"props":1321,"children":1323},{"className":1322},[],[1324],{"type":33,"value":1325},"inventory:{id}",{"type":27,"tag":36,"props":1327,"children":1328},{},[1329],{"type":33,"value":1330},"当你更新库存时：",{"type":27,"tag":47,"props":1332,"children":1333},{},[1334,1344],{"type":27,"tag":51,"props":1335,"children":1336},{},[1337,1339],{"type":33,"value":1338},"失效 ",{"type":27,"tag":830,"props":1340,"children":1342},{"className":1341},[],[1343],{"type":33,"value":1325},{"type":27,"tag":51,"props":1345,"children":1346},{},[1347,1349,1354],{"type":33,"value":1348},"可能也失效 ",{"type":27,"tag":830,"props":1350,"children":1352},{"className":1351},[],[1353],{"type":33,"value":1307},{"type":33,"value":1355},"（如果详情页展示库存）",{"type":27,"tag":36,"props":1357,"children":1358},{},[1359],{"type":33,"value":1360},"这样你可以把失效做成一套规则，而不是散落在业务代码里。",{"type":27,"tag":519,"props":1362,"children":1364},{"id":1363},"_52-不要用全站失效当默认",[1365],{"type":33,"value":1366},"5.2 不要用“全站失效”当默认",{"type":27,"tag":36,"props":1368,"children":1369},{},[1370,1376],{"type":27,"tag":830,"props":1371,"children":1373},{"className":1372},[],[1374],{"type":33,"value":1375},"revalidatePath('/')",{"type":33,"value":1377},"、清 CDN 全站缓存，短期看省事，长期一定出问题：",{"type":27,"tag":47,"props":1379,"children":1380},{},[1381,1386,1391],{"type":27,"tag":51,"props":1382,"children":1383},{},[1384],{"type":33,"value":1385},"命中率暴跌",{"type":27,"tag":51,"props":1387,"children":1388},{},[1389],{"type":33,"value":1390},"源站被打穿",{"type":27,"tag":51,"props":1392,"children":1393},{},[1394],{"type":33,"value":1395},"回归定位困难",{"type":27,"tag":705,"props":1397,"children":1398},{},[],{"type":27,"tag":28,"props":1400,"children":1402},{"id":1401},"_6-缓存与权限最危险的组合",[1403],{"type":33,"value":1404},"6. 缓存与权限：最危险的组合",{"type":27,"tag":519,"props":1406,"children":1408},{"id":1407},"_61-三条硬规则",[1409],{"type":33,"value":1410},"6.1 三条硬规则",{"type":27,"tag":47,"props":1412,"children":1413},{},[1414,1419,1424],{"type":27,"tag":51,"props":1415,"children":1416},{},[1417],{"type":33,"value":1418},"用户态响应不要进 CDN",{"type":27,"tag":51,"props":1420,"children":1421},{},[1422],{"type":33,"value":1423},"缓存 key 必须包含权限维度（userId/role）",{"type":27,"tag":51,"props":1425,"children":1426},{},[1427],{"type":33,"value":1428},"SSR 页面要明确区分“公共数据”与“私有数据”",{"type":27,"tag":519,"props":1430,"children":1432},{"id":1431},"_62-常见事故模式",[1433],{"type":33,"value":1434},"6.2 常见事故模式",{"type":27,"tag":47,"props":1436,"children":1437},{},[1438,1443,1448],{"type":27,"tag":51,"props":1439,"children":1440},{},[1441],{"type":33,"value":1442},"详情页同时展示公共内容 + 用户私有信息（例如是否收藏）",{"type":27,"tag":51,"props":1444,"children":1445},{},[1446],{"type":33,"value":1447},"你把整页缓存了",{"type":27,"tag":51,"props":1449,"children":1450},{},[1451],{"type":33,"value":1452},"结果：用户私有信息被缓存并泄漏",{"type":27,"tag":36,"props":1454,"children":1455},{},[1456],{"type":33,"value":1457},"正确做法：",{"type":27,"tag":47,"props":1459,"children":1460},{},[1461,1466],{"type":27,"tag":51,"props":1462,"children":1463},{},[1464],{"type":33,"value":1465},"公共内容可缓存",{"type":27,"tag":51,"props":1467,"children":1468},{},[1469],{"type":33,"value":1470},"私有信息走客户端请求或单独的私有 API（不缓存）",{"type":27,"tag":705,"props":1472,"children":1473},{},[],{"type":27,"tag":28,"props":1475,"children":1477},{"id":1476},"_7-可观测性让缓存变成可量化系统",[1478],{"type":33,"value":1479},"7. 可观测性：让缓存变成“可量化系统”",{"type":27,"tag":36,"props":1481,"children":1482},{},[1483],{"type":33,"value":1484},"你至少需要这些指标：",{"type":27,"tag":47,"props":1486,"children":1487},{},[1488,1493,1498,1503,1508],{"type":27,"tag":51,"props":1489,"children":1490},{},[1491],{"type":33,"value":1492},"CDN 命中率（hit/miss）",{"type":27,"tag":51,"props":1494,"children":1495},{},[1496],{"type":33,"value":1497},"源站 QPS",{"type":27,"tag":51,"props":1499,"children":1500},{},[1501],{"type":33,"value":1502},"TTFB 分布（p50/p95）",{"type":27,"tag":51,"props":1504,"children":1505},{},[1506],{"type":33,"value":1507},"revalidate 调用量与耗时",{"type":27,"tag":51,"props":1509,"children":1510},{},[1511],{"type":33,"value":1512},"失效失败率",{"type":27,"tag":36,"props":1514,"children":1515},{},[1516],{"type":33,"value":1517},"日志建议：",{"type":27,"tag":47,"props":1519,"children":1520},{},[1521,1534],{"type":27,"tag":51,"props":1522,"children":1523},{},[1524,1526,1532],{"type":33,"value":1525},"给每个请求注入 ",{"type":27,"tag":830,"props":1527,"children":1529},{"className":1528},[],[1530],{"type":33,"value":1531},"cacheStatus",{"type":33,"value":1533},"（HIT/MISS/BYPASS）",{"type":27,"tag":51,"props":1535,"children":1536},{},[1537,1539,1545],{"type":33,"value":1538},"记录 ",{"type":27,"tag":830,"props":1540,"children":1542},{"className":1541},[],[1543],{"type":33,"value":1544},"cacheKey",{"type":33,"value":1546}," 的关键维度（注意脱敏）",{"type":27,"tag":705,"props":1548,"children":1549},{},[],{"type":27,"tag":28,"props":1551,"children":1553},{"id":1552},"_8-一份可直接执行的缓存策略模板",[1554],{"type":33,"value":1555},"8. 一份可直接执行的缓存策略模板",{"type":27,"tag":519,"props":1557,"children":1559},{"id":1558},"_81-公共内容页文章落地页",[1560],{"type":33,"value":1561},"8.1 公共内容页（文章、落地页）",{"type":27,"tag":47,"props":1563,"children":1564},{},[1565,1576,1589],{"type":27,"tag":51,"props":1566,"children":1567},{},[1568,1570],{"type":33,"value":1569},"CDN：",{"type":27,"tag":830,"props":1571,"children":1573},{"className":1572},[],[1574],{"type":33,"value":1575},"s-maxage=600, stale-while-revalidate=86400",{"type":27,"tag":51,"props":1577,"children":1578},{},[1579,1581,1587],{"type":33,"value":1580},"App：允许 fetch cache，tag 以 ",{"type":27,"tag":830,"props":1582,"children":1584},{"className":1583},[],[1585],{"type":33,"value":1586},"content:*",{"type":33,"value":1588}," 组织",{"type":27,"tag":51,"props":1590,"children":1591},{},[1592,1594],{"type":33,"value":1593},"写操作：发布文章时 ",{"type":27,"tag":830,"props":1595,"children":1597},{"className":1596},[],[1598],{"type":33,"value":1599},"revalidateTag('content:article')",{"type":27,"tag":519,"props":1601,"children":1603},{"id":1602},"_82-列表-详情强一致性要求不高",[1604],{"type":33,"value":1605},"8.2 列表 + 详情（强一致性要求不高）",{"type":27,"tag":47,"props":1607,"children":1608},{},[1609,1620,1631],{"type":27,"tag":51,"props":1610,"children":1611},{},[1612,1614],{"type":33,"value":1613},"详情：tag ",{"type":27,"tag":830,"props":1615,"children":1617},{"className":1616},[],[1618],{"type":33,"value":1619},"entity:{id}",{"type":27,"tag":51,"props":1621,"children":1622},{},[1623,1625],{"type":33,"value":1624},"列表：tag ",{"type":27,"tag":830,"props":1626,"children":1628},{"className":1627},[],[1629],{"type":33,"value":1630},"entity:list",{"type":27,"tag":51,"props":1632,"children":1633},{},[1634,1636,1641,1643],{"type":33,"value":1635},"更新：失效 ",{"type":27,"tag":830,"props":1637,"children":1639},{"className":1638},[],[1640],{"type":33,"value":1619},{"type":33,"value":1642}," + ",{"type":27,"tag":830,"props":1644,"children":1646},{"className":1645},[],[1647],{"type":33,"value":1630},{"type":27,"tag":519,"props":1649,"children":1651},{"id":1650},"_83-强一致性库存余额",[1652],{"type":33,"value":1653},"8.3 强一致性（库存、余额）",{"type":27,"tag":47,"props":1655,"children":1656},{},[1657,1662,1667],{"type":27,"tag":51,"props":1658,"children":1659},{},[1660],{"type":33,"value":1661},"默认不缓存",{"type":27,"tag":51,"props":1663,"children":1664},{},[1665],{"type":33,"value":1666},"或只做极短 TTL（1~3s）",{"type":27,"tag":51,"props":1668,"children":1669},{},[1670],{"type":33,"value":1671},"必须有幂等与容错",{"type":27,"tag":705,"props":1673,"children":1674},{},[],{"type":27,"tag":28,"props":1676,"children":1678},{"id":1677},"_9-检查清单上线前必过",[1679],{"type":33,"value":1680},"9. 检查清单（上线前必过）",{"type":27,"tag":47,"props":1682,"children":1684},{"className":1683},[434],[1685,1694,1703,1712,1721,1730],{"type":27,"tag":51,"props":1686,"children":1688},{"className":1687},[439],[1689,1692],{"type":27,"tag":442,"props":1690,"children":1691},{"disabled":444,"type":445},[],{"type":33,"value":1693}," 哪些路由是 public/private？是否明确",{"type":27,"tag":51,"props":1695,"children":1697},{"className":1696},[439],[1698,1701],{"type":27,"tag":442,"props":1699,"children":1700},{"disabled":444,"type":445},[],{"type":33,"value":1702}," CDN cache key 是否会被无关 query 污染",{"type":27,"tag":51,"props":1704,"children":1706},{"className":1705},[439],[1707,1710],{"type":27,"tag":442,"props":1708,"children":1709},{"disabled":444,"type":445},[],{"type":33,"value":1711}," 用户态响应是否有 no-store",{"type":27,"tag":51,"props":1713,"children":1715},{"className":1714},[439],[1716,1719],{"type":27,"tag":442,"props":1717,"children":1718},{"disabled":444,"type":445},[],{"type":33,"value":1720}," 写操作是否有明确的 tag/path 失效策略",{"type":27,"tag":51,"props":1722,"children":1724},{"className":1723},[439],[1725,1728],{"type":27,"tag":442,"props":1726,"children":1727},{"disabled":444,"type":445},[],{"type":33,"value":1729}," 是否有命中率与回源监控",{"type":27,"tag":51,"props":1731,"children":1733},{"className":1732},[439],[1734,1737],{"type":27,"tag":442,"props":1735,"children":1736},{"disabled":444,"type":445},[],{"type":33,"value":1738}," 回滚策略是什么（关缓存、降级）",{"type":27,"tag":705,"props":1740,"children":1741},{},[],{"type":27,"tag":28,"props":1743,"children":1745},{"id":1744},"总结",[1746],{"type":33,"value":1744},{"type":27,"tag":36,"props":1748,"children":1749},{},[1750],{"type":33,"value":1751},"缓存策略的本质是：",{"type":27,"tag":47,"props":1753,"children":1754},{},[1755,1760,1765],{"type":27,"tag":51,"props":1756,"children":1757},{},[1758],{"type":33,"value":1759},"把“快”变成可控的工程系统",{"type":27,"tag":51,"props":1761,"children":1762},{},[1763],{"type":33,"value":1764},"把“一致性”变成可证明的规则",{"type":27,"tag":51,"props":1766,"children":1767},{},[1768],{"type":33,"value":1769},"把“失效”变成可观测、可回滚的流程",{"title":7,"searchDepth":598,"depth":598,"links":1771},[1772,1773,1776,1780,1784,1788,1792,1796,1797,1802,1803],{"id":623,"depth":601,"text":623},{"id":710,"depth":601,"text":713,"children":1774},[1775],{"id":787,"depth":598,"text":790},{"id":814,"depth":601,"text":817,"children":1777},[1778,1779],{"id":890,"depth":598,"text":893},{"id":936,"depth":598,"text":939},{"id":979,"depth":601,"text":982,"children":1781},[1782,1783],{"id":1008,"depth":598,"text":1011},{"id":1097,"depth":598,"text":1100},{"id":1138,"depth":601,"text":1141,"children":1785},[1786,1787],{"id":1172,"depth":598,"text":1175},{"id":1206,"depth":598,"text":1209},{"id":1258,"depth":601,"text":1261,"children":1789},[1790,1791],{"id":1287,"depth":598,"text":1290},{"id":1363,"depth":598,"text":1366},{"id":1401,"depth":601,"text":1404,"children":1793},[1794,1795],{"id":1407,"depth":598,"text":1410},{"id":1431,"depth":598,"text":1434},{"id":1476,"depth":601,"text":1479},{"id":1552,"depth":601,"text":1555,"children":1798},[1799,1800,1801],{"id":1558,"depth":598,"text":1561},{"id":1602,"depth":598,"text":1605},{"id":1650,"depth":598,"text":1653},{"id":1677,"depth":601,"text":1680},{"id":1744,"depth":601,"text":1744},"content:topics:next:cache-strategy-deep-dive.md","topics/next/cache-strategy-deep-dive.md","topics/next/cache-strategy-deep-dive",{"_path":1808,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1809,"description":1810,"date":625,"topic":5,"author":11,"tags":1811,"image":1815,"featured":444,"readingTime":633,"body":1816,"_type":615,"_id":2614,"_source":617,"_file":2615,"_stem":2616,"_extension":620},"/topics/next/isr-practice","增量静态再生 (ISR) 实战","从缓存语义与一致性边界出发，讲清 ISR 的原理、适用场景与落地细节，并给出可直接复用的页面设计、失效策略与线上排障方法。",[628,1812,143,1813,1814],"ISR","SSG","SEO","/images/topics/next/isr.jpg",{"type":24,"children":1817,"toc":2589},[1818,1823,1828,1839,1844,1857,1862,1890,1893,1899,1904,1937,1942,1945,1951,1956,1969,1974,1987,1990,1996,2002,2007,2025,2030,2043,2049,2053,2071,2075,2093,2096,2102,2108,2113,2118,2131,2137,2142,2147,2160,2164,2177,2180,2186,2191,2196,2209,2214,2232,2235,2241,2246,2282,2287,2312,2317,2320,2326,2332,2337,2355,2361,2379,2385,2390,2408,2414,2427,2433,2446,2450,2463,2469,2474,2479,2492,2495,2501,2559,2562,2566,2571],{"type":27,"tag":28,"props":1819,"children":1821},{"id":1820},"增量静态再生-isr-实战",[1822],{"type":33,"value":1809},{"type":27,"tag":36,"props":1824,"children":1825},{},[1826],{"type":33,"value":1827},"ISR（Incremental Static Regeneration）经常被误解为“更聪明的 SSG”。",{"type":27,"tag":36,"props":1829,"children":1830},{},[1831,1833,1838],{"type":33,"value":1832},"更准确的说法是：ISR 是一套把“静态化收益”与“内容更新需求”折中起来的",{"type":27,"tag":646,"props":1834,"children":1835},{},[1836],{"type":33,"value":1837},"缓存与再生成协议",{"type":33,"value":652},{"type":27,"tag":36,"props":1840,"children":1841},{},[1842],{"type":33,"value":1843},"它解决的核心矛盾是：",{"type":27,"tag":47,"props":1845,"children":1846},{},[1847,1852],{"type":27,"tag":51,"props":1848,"children":1849},{},[1850],{"type":33,"value":1851},"你想要静态页面的性能与稳定性（低 TTFB、CDN 命中、高并发能力）",{"type":27,"tag":51,"props":1853,"children":1854},{},[1855],{"type":33,"value":1856},"你又希望内容能及时更新（分钟级甚至秒级）",{"type":27,"tag":36,"props":1858,"children":1859},{},[1860],{"type":33,"value":1861},"这篇文章按“上生产能跑稳”为标准，讲清：",{"type":27,"tag":47,"props":1863,"children":1864},{},[1865,1870,1875,1880,1885],{"type":27,"tag":51,"props":1866,"children":1867},{},[1868],{"type":33,"value":1869},"ISR 的工作原理与心智模型",{"type":27,"tag":51,"props":1871,"children":1872},{},[1873],{"type":33,"value":1874},"适用场景与反例",{"type":27,"tag":51,"props":1876,"children":1877},{},[1878],{"type":33,"value":1879},"页面设计（列表/详情/搜索）",{"type":27,"tag":51,"props":1881,"children":1882},{},[1883],{"type":33,"value":1884},"失效策略：时间驱动 vs 事件驱动",{"type":27,"tag":51,"props":1886,"children":1887},{},[1888],{"type":33,"value":1889},"线上排障：为什么更新不生效/为什么频繁回源",{"type":27,"tag":705,"props":1891,"children":1892},{},[],{"type":27,"tag":28,"props":1894,"children":1896},{"id":1895},"_1-先统一语言你到底想解决什么",[1897],{"type":33,"value":1898},"1. 先统一语言：你到底想解决什么？",{"type":27,"tag":36,"props":1900,"children":1901},{},[1902],{"type":33,"value":1903},"在真实业务里，“内容更新”通常有三种等级：",{"type":27,"tag":215,"props":1905,"children":1906},{},[1907,1917,1927],{"type":27,"tag":51,"props":1908,"children":1909},{},[1910,1915],{"type":27,"tag":646,"props":1911,"children":1912},{},[1913],{"type":33,"value":1914},"允许延迟",{"type":33,"value":1916},"：比如文章页、帮助文档、营销页，更新延迟 5~30 分钟都能接受",{"type":27,"tag":51,"props":1918,"children":1919},{},[1920,1925],{"type":27,"tag":646,"props":1921,"children":1922},{},[1923],{"type":33,"value":1924},"弱一致",{"type":33,"value":1926},"：比如商品价格、库存展示（可能需要更短 TTL，但可以接受短时间旧值）",{"type":27,"tag":51,"props":1928,"children":1929},{},[1930,1935],{"type":27,"tag":646,"props":1931,"children":1932},{},[1933],{"type":33,"value":1934},"强一致",{"type":33,"value":1936},"：比如支付结果、权限信息，不能用 ISR 兜底",{"type":27,"tag":36,"props":1938,"children":1939},{},[1940],{"type":33,"value":1941},"ISR 最适合第 1 类，谨慎用于第 2 类，不适合第 3 类。",{"type":27,"tag":705,"props":1943,"children":1944},{},[],{"type":27,"tag":28,"props":1946,"children":1948},{"id":1947},"_2-isr-的心智模型把它当成cdn-后的再生成缓存",[1949],{"type":33,"value":1950},"2. ISR 的心智模型：把它当成“CDN 后的再生成缓存”",{"type":27,"tag":36,"props":1952,"children":1953},{},[1954],{"type":33,"value":1955},"你可以把 ISR 看作两层：",{"type":27,"tag":47,"props":1957,"children":1958},{},[1959,1964],{"type":27,"tag":51,"props":1960,"children":1961},{},[1962],{"type":33,"value":1963},"CDN：缓存最终 HTML（或 RSC payload）",{"type":27,"tag":51,"props":1965,"children":1966},{},[1967],{"type":33,"value":1968},"应用（Next.js）：缓存页面生成结果，并按规则触发再生成",{"type":27,"tag":36,"props":1970,"children":1971},{},[1972],{"type":33,"value":1973},"关键点：",{"type":27,"tag":47,"props":1975,"children":1976},{},[1977,1982],{"type":27,"tag":51,"props":1978,"children":1979},{},[1980],{"type":33,"value":1981},"ISR 不是“每次请求都重新生成”，而是“绝大多数时候直接命中缓存”",{"type":27,"tag":51,"props":1983,"children":1984},{},[1985],{"type":33,"value":1986},"再生成是“受控发生”的",{"type":27,"tag":705,"props":1988,"children":1989},{},[],{"type":27,"tag":28,"props":1991,"children":1993},{"id":1992},"_3-两种驱动方式时间驱动-vs-事件驱动",[1994],{"type":33,"value":1995},"3. 两种驱动方式：时间驱动 vs 事件驱动",{"type":27,"tag":519,"props":1997,"children":1999},{"id":1998},"_31-时间驱动revalidate-秒数",[2000],{"type":33,"value":2001},"3.1 时间驱动（revalidate 秒数）",{"type":27,"tag":36,"props":2003,"children":2004},{},[2005],{"type":33,"value":2006},"特点：",{"type":27,"tag":47,"props":2008,"children":2009},{},[2010,2015,2020],{"type":27,"tag":51,"props":2011,"children":2012},{},[2013],{"type":33,"value":2014},"简单",{"type":27,"tag":51,"props":2016,"children":2017},{},[2018],{"type":33,"value":2019},"稳定",{"type":27,"tag":51,"props":2021,"children":2022},{},[2023],{"type":33,"value":2024},"但更新延迟不可控（取决于 TTL 与访问触发）",{"type":27,"tag":36,"props":2026,"children":2027},{},[2028],{"type":33,"value":2029},"适用：",{"type":27,"tag":47,"props":2031,"children":2032},{},[2033,2038],{"type":27,"tag":51,"props":2034,"children":2035},{},[2036],{"type":33,"value":2037},"内容更新不频繁",{"type":27,"tag":51,"props":2039,"children":2040},{},[2041],{"type":33,"value":2042},"不需要“发布即生效”",{"type":27,"tag":519,"props":2044,"children":2046},{"id":2045},"_32-事件驱动按需再验证-webhook",[2047],{"type":33,"value":2048},"3.2 事件驱动（按需再验证 / webhook）",{"type":27,"tag":36,"props":2050,"children":2051},{},[2052],{"type":33,"value":2006},{"type":27,"tag":47,"props":2054,"children":2055},{},[2056,2061,2066],{"type":27,"tag":51,"props":2057,"children":2058},{},[2059],{"type":33,"value":2060},"发布后可快速生效",{"type":27,"tag":51,"props":2062,"children":2063},{},[2064],{"type":33,"value":2065},"更可控",{"type":27,"tag":51,"props":2067,"children":2068},{},[2069],{"type":33,"value":2070},"需要你有“内容发布事件”与安全机制",{"type":27,"tag":36,"props":2072,"children":2073},{},[2074],{"type":33,"value":2029},{"type":27,"tag":47,"props":2076,"children":2077},{},[2078,2083,2088],{"type":27,"tag":51,"props":2079,"children":2080},{},[2081],{"type":33,"value":2082},"CMS 发布文章",{"type":27,"tag":51,"props":2084,"children":2085},{},[2086],{"type":33,"value":2087},"商品信息变更",{"type":27,"tag":51,"props":2089,"children":2090},{},[2091],{"type":33,"value":2092},"专题页更新",{"type":27,"tag":705,"props":2094,"children":2095},{},[],{"type":27,"tag":28,"props":2097,"children":2099},{"id":2098},"_4-典型页面怎么做列表-详情",[2100],{"type":33,"value":2101},"4. 典型页面怎么做：列表 + 详情",{"type":27,"tag":519,"props":2103,"children":2105},{"id":2104},"_41-详情页优先事件驱动",[2106],{"type":33,"value":2107},"4.1 详情页：优先事件驱动",{"type":27,"tag":36,"props":2109,"children":2110},{},[2111],{"type":33,"value":2112},"详情页更新的最佳体验通常是“发布即生效”。",{"type":27,"tag":36,"props":2114,"children":2115},{},[2116],{"type":33,"value":2117},"策略：",{"type":27,"tag":47,"props":2119,"children":2120},{},[2121,2126],{"type":27,"tag":51,"props":2122,"children":2123},{},[2124],{"type":33,"value":2125},"详情页使用 ISR（或静态 + 按需再验证）",{"type":27,"tag":51,"props":2127,"children":2128},{},[2129],{"type":33,"value":2130},"CMS 发布时调用 webhook，让应用对特定 path/tag 失效",{"type":27,"tag":519,"props":2132,"children":2134},{"id":2133},"_42-列表页注意聚合页放大效应",[2135],{"type":33,"value":2136},"4.2 列表页：注意“聚合页放大效应”",{"type":27,"tag":36,"props":2138,"children":2139},{},[2140],{"type":33,"value":2141},"列表页（例如文章列表、商品列表）会被大量访问，且它的内容聚合了很多详情。",{"type":27,"tag":36,"props":2143,"children":2144},{},[2145],{"type":33,"value":2146},"常见坑：",{"type":27,"tag":47,"props":2148,"children":2149},{},[2150,2155],{"type":27,"tag":51,"props":2151,"children":2152},{},[2153],{"type":33,"value":2154},"每次新增一篇文章都要失效列表页",{"type":27,"tag":51,"props":2156,"children":2157},{},[2158],{"type":33,"value":2159},"导致列表页频繁再生成 → 回源增多",{"type":27,"tag":36,"props":2161,"children":2162},{},[2163],{"type":33,"value":1105},{"type":27,"tag":47,"props":2165,"children":2166},{},[2167,2172],{"type":27,"tag":51,"props":2168,"children":2169},{},[2170],{"type":33,"value":2171},"列表页采用较长 TTL（例如 10~30 分钟）",{"type":27,"tag":51,"props":2173,"children":2174},{},[2175],{"type":33,"value":2176},"或把“最新内容”拆成单独模块，使用客户端请求/边缘 KV",{"type":27,"tag":705,"props":2178,"children":2179},{},[],{"type":27,"tag":28,"props":2181,"children":2183},{"id":2182},"_5-数据获取与缓存别把-isr-做成慢-ssr",[2184],{"type":33,"value":2185},"5. 数据获取与缓存：别把 ISR 做成“慢 SSR”",{"type":27,"tag":36,"props":2187,"children":2188},{},[2189],{"type":33,"value":2190},"ISR 的性能收益来自“生成一次 → 复用很多次”。",{"type":27,"tag":36,"props":2192,"children":2193},{},[2194],{"type":33,"value":2195},"所以你要避免：",{"type":27,"tag":47,"props":2197,"children":2198},{},[2199,2204],{"type":27,"tag":51,"props":2200,"children":2201},{},[2202],{"type":33,"value":2203},"页面生成时做大量慢查询",{"type":27,"tag":51,"props":2205,"children":2206},{},[2207],{"type":33,"value":2208},"页面生成时串行请求多个上游",{"type":27,"tag":36,"props":2210,"children":2211},{},[2212],{"type":33,"value":2213},"实践建议：",{"type":27,"tag":47,"props":2215,"children":2216},{},[2217,2222,2227],{"type":27,"tag":51,"props":2218,"children":2219},{},[2220],{"type":33,"value":2221},"生成路径尽量轻（prefetch、批量接口、缓存）",{"type":27,"tag":51,"props":2223,"children":2224},{},[2225],{"type":33,"value":2226},"对上游请求设置超时",{"type":27,"tag":51,"props":2228,"children":2229},{},[2230],{"type":33,"value":2231},"做并行请求",{"type":27,"tag":705,"props":2233,"children":2234},{},[],{"type":27,"tag":28,"props":2236,"children":2238},{"id":2237},"_6-失效策略设计从靠感觉到有规则",[2239],{"type":33,"value":2240},"6. 失效策略设计：从“靠感觉”到“有规则”",{"type":27,"tag":36,"props":2242,"children":2243},{},[2244],{"type":33,"value":2245},"建议采用“域驱动失效”思路：",{"type":27,"tag":47,"props":2247,"children":2248},{},[2249,2260,2271],{"type":27,"tag":51,"props":2250,"children":2251},{},[2252,2254],{"type":33,"value":2253},"文章：",{"type":27,"tag":830,"props":2255,"children":2257},{"className":2256},[],[2258],{"type":33,"value":2259},"article:{slug}",{"type":27,"tag":51,"props":2261,"children":2262},{},[2263,2265],{"type":33,"value":2264},"文章列表：",{"type":27,"tag":830,"props":2266,"children":2268},{"className":2267},[],[2269],{"type":33,"value":2270},"article:list",{"type":27,"tag":51,"props":2272,"children":2273},{},[2274,2276],{"type":33,"value":2275},"专题：",{"type":27,"tag":830,"props":2277,"children":2279},{"className":2278},[],[2280],{"type":33,"value":2281},"topic:{name}",{"type":27,"tag":36,"props":2283,"children":2284},{},[2285],{"type":33,"value":2286},"当某篇文章更新：",{"type":27,"tag":47,"props":2288,"children":2289},{},[2290,2300],{"type":27,"tag":51,"props":2291,"children":2292},{},[2293,2295],{"type":33,"value":2294},"必失效：",{"type":27,"tag":830,"props":2296,"children":2298},{"className":2297},[],[2299],{"type":33,"value":2259},{"type":27,"tag":51,"props":2301,"children":2302},{},[2303,2305,2310],{"type":33,"value":2304},"可选失效：",{"type":27,"tag":830,"props":2306,"children":2308},{"className":2307},[],[2309],{"type":33,"value":2270},{"type":33,"value":2311},"（看你是否要求“列表立即出现最新文章”）",{"type":27,"tag":36,"props":2313,"children":2314},{},[2315],{"type":33,"value":2316},"这样你能解释每一次失效，而不是“全站清缓存”。",{"type":27,"tag":705,"props":2318,"children":2319},{},[],{"type":27,"tag":28,"props":2321,"children":2323},{"id":2322},"_7-线上排障isr-最常见的-6-个问题",[2324],{"type":33,"value":2325},"7. 线上排障：ISR 最常见的 6 个问题",{"type":27,"tag":519,"props":2327,"children":2329},{"id":2328},"_71-发布了但页面不更新",[2330],{"type":33,"value":2331},"7.1 “发布了但页面不更新”",{"type":27,"tag":36,"props":2333,"children":2334},{},[2335],{"type":33,"value":2336},"排查顺序：",{"type":27,"tag":47,"props":2338,"children":2339},{},[2340,2345,2350],{"type":27,"tag":51,"props":2341,"children":2342},{},[2343],{"type":33,"value":2344},"webhook 是否触发？是否被鉴权拦截？",{"type":27,"tag":51,"props":2346,"children":2347},{},[2348],{"type":33,"value":2349},"失效的是正确的 path/tag 吗？",{"type":27,"tag":51,"props":2351,"children":2352},{},[2353],{"type":33,"value":2354},"CDN 是否仍在强缓存旧内容？（看响应头、Cache-Status）",{"type":27,"tag":519,"props":2356,"children":2358},{"id":2357},"_72-页面更新了但-seo-抓不到",[2359],{"type":33,"value":2360},"7.2 “页面更新了但 SEO 抓不到”",{"type":27,"tag":47,"props":2362,"children":2363},{},[2364,2369,2374],{"type":27,"tag":51,"props":2365,"children":2366},{},[2367],{"type":33,"value":2368},"sitemap 是否更新",{"type":27,"tag":51,"props":2370,"children":2371},{},[2372],{"type":33,"value":2373},"canonical/robots 是否正确",{"type":27,"tag":51,"props":2375,"children":2376},{},[2377],{"type":33,"value":2378},"是否把重要内容放在客户端渲染",{"type":27,"tag":519,"props":2380,"children":2382},{"id":2381},"_73-回源突然暴增",[2383],{"type":33,"value":2384},"7.3 “回源突然暴增”",{"type":27,"tag":36,"props":2386,"children":2387},{},[2388],{"type":33,"value":2389},"常见原因：",{"type":27,"tag":47,"props":2391,"children":2392},{},[2393,2398,2403],{"type":27,"tag":51,"props":2394,"children":2395},{},[2396],{"type":33,"value":2397},"TTL 设太短",{"type":27,"tag":51,"props":2399,"children":2400},{},[2401],{"type":33,"value":2402},"聚合页频繁失效",{"type":27,"tag":51,"props":2404,"children":2405},{},[2406],{"type":33,"value":2407},"缓存命中率被 query 污染（utm）",{"type":27,"tag":519,"props":2409,"children":2411},{"id":2410},"_74-某些地区更新很慢",[2412],{"type":33,"value":2413},"7.4 “某些地区更新很慢”",{"type":27,"tag":47,"props":2415,"children":2416},{},[2417,2422],{"type":27,"tag":51,"props":2418,"children":2419},{},[2420],{"type":33,"value":2421},"CDN 分区缓存",{"type":27,"tag":51,"props":2423,"children":2424},{},[2425],{"type":33,"value":2426},"边缘节点回源延迟",{"type":27,"tag":519,"props":2428,"children":2430},{"id":2429},"_75-低峰正常高峰崩",[2431],{"type":33,"value":2432},"7.5 “低峰正常，高峰崩”",{"type":27,"tag":47,"props":2434,"children":2435},{},[2436,2441],{"type":27,"tag":51,"props":2437,"children":2438},{},[2439],{"type":33,"value":2440},"再生成并发过高",{"type":27,"tag":51,"props":2442,"children":2443},{},[2444],{"type":33,"value":2445},"上游服务扛不住",{"type":27,"tag":36,"props":2447,"children":2448},{},[2449],{"type":33,"value":2117},{"type":27,"tag":47,"props":2451,"children":2452},{},[2453,2458],{"type":27,"tag":51,"props":2454,"children":2455},{},[2456],{"type":33,"value":2457},"限制再生成并发",{"type":27,"tag":51,"props":2459,"children":2460},{},[2461],{"type":33,"value":2462},"对再生成做队列化",{"type":27,"tag":519,"props":2464,"children":2466},{"id":2465},"_76-用户态数据被缓存",[2467],{"type":33,"value":2468},"7.6 “用户态数据被缓存”",{"type":27,"tag":36,"props":2470,"children":2471},{},[2472],{"type":33,"value":2473},"这是最危险的。",{"type":27,"tag":36,"props":2475,"children":2476},{},[2477],{"type":33,"value":2478},"规则：",{"type":27,"tag":47,"props":2480,"children":2481},{},[2482,2487],{"type":27,"tag":51,"props":2483,"children":2484},{},[2485],{"type":33,"value":2486},"用户态页面不要 ISR",{"type":27,"tag":51,"props":2488,"children":2489},{},[2490],{"type":33,"value":2491},"或把私有信息拆出（客户端请求）",{"type":27,"tag":705,"props":2493,"children":2494},{},[],{"type":27,"tag":28,"props":2496,"children":2498},{"id":2497},"_8-上线检查清单",[2499],{"type":33,"value":2500},"8. 上线检查清单",{"type":27,"tag":47,"props":2502,"children":2504},{"className":2503},[434],[2505,2514,2523,2532,2541,2550],{"type":27,"tag":51,"props":2506,"children":2508},{"className":2507},[439],[2509,2512],{"type":27,"tag":442,"props":2510,"children":2511},{"disabled":444,"type":445},[],{"type":33,"value":2513}," 哪些路由使用 ISR？是否排除用户态页面",{"type":27,"tag":51,"props":2515,"children":2517},{"className":2516},[439],[2518,2521],{"type":27,"tag":442,"props":2519,"children":2520},{"disabled":444,"type":445},[],{"type":33,"value":2522}," 详情页与列表页的 TTL 是否合理",{"type":27,"tag":51,"props":2524,"children":2526},{"className":2525},[439],[2527,2530],{"type":27,"tag":442,"props":2528,"children":2529},{"disabled":444,"type":445},[],{"type":33,"value":2531}," 是否有事件驱动失效（CMS webhook）",{"type":27,"tag":51,"props":2533,"children":2535},{"className":2534},[439],[2536,2539],{"type":27,"tag":442,"props":2537,"children":2538},{"disabled":444,"type":445},[],{"type":33,"value":2540}," CDN cache key 是否会被 query 污染",{"type":27,"tag":51,"props":2542,"children":2544},{"className":2543},[439],[2545,2548],{"type":27,"tag":442,"props":2546,"children":2547},{"disabled":444,"type":445},[],{"type":33,"value":2549}," 是否有命中率/回源/QPS 监控",{"type":27,"tag":51,"props":2551,"children":2553},{"className":2552},[439],[2554,2557],{"type":27,"tag":442,"props":2555,"children":2556},{"disabled":444,"type":445},[],{"type":33,"value":2558}," 再生成失败是否可观测（日志、报警）",{"type":27,"tag":705,"props":2560,"children":2561},{},[],{"type":27,"tag":28,"props":2563,"children":2564},{"id":1744},[2565],{"type":33,"value":1744},{"type":27,"tag":36,"props":2567,"children":2568},{},[2569],{"type":33,"value":2570},"ISR 的正确用法是：",{"type":27,"tag":47,"props":2572,"children":2573},{},[2574,2579,2584],{"type":27,"tag":51,"props":2575,"children":2576},{},[2577],{"type":33,"value":2578},"把它当成“带可控失效的静态缓存系统”",{"type":27,"tag":51,"props":2580,"children":2581},{},[2582],{"type":33,"value":2583},"用规则设计失效，而不是全站清缓存",{"type":27,"tag":51,"props":2585,"children":2586},{},[2587],{"type":33,"value":2588},"用监控保证它在高峰依然稳定",{"title":7,"searchDepth":598,"depth":598,"links":2590},[2591,2592,2593,2594,2598,2602,2603,2604,2612,2613],{"id":1820,"depth":601,"text":1809},{"id":1895,"depth":601,"text":1898},{"id":1947,"depth":601,"text":1950},{"id":1992,"depth":601,"text":1995,"children":2595},[2596,2597],{"id":1998,"depth":598,"text":2001},{"id":2045,"depth":598,"text":2048},{"id":2098,"depth":601,"text":2101,"children":2599},[2600,2601],{"id":2104,"depth":598,"text":2107},{"id":2133,"depth":598,"text":2136},{"id":2182,"depth":601,"text":2185},{"id":2237,"depth":601,"text":2240},{"id":2322,"depth":601,"text":2325,"children":2605},[2606,2607,2608,2609,2610,2611],{"id":2328,"depth":598,"text":2331},{"id":2357,"depth":598,"text":2360},{"id":2381,"depth":598,"text":2384},{"id":2410,"depth":598,"text":2413},{"id":2429,"depth":598,"text":2432},{"id":2465,"depth":598,"text":2468},{"id":2497,"depth":601,"text":2500},{"id":1744,"depth":601,"text":1744},"content:topics:next:isr-practice.md","topics/next/isr-practice.md","topics/next/isr-practice",{"_path":2618,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":2619,"description":2620,"date":625,"topic":5,"author":11,"tags":2621,"image":2625,"featured":444,"readingTime":2626,"body":2627,"_type":615,"_id":3740,"_source":617,"_file":3741,"_stem":3742,"_extension":620},"/topics/next/server-actions-complete-guide","Server Actions 完整指南","从工作原理到安全边界与缓存语义，系统讲透 Next.js Server Actions 的编程模型，并给出可直接落地的工程化实践范式。",[628,2622,629,2623,2624,143],"Server Actions","表单","安全","/images/topics/next/server-actions.jpg",20,{"type":24,"children":2628,"toc":3706},[2629,2634,2645,2657,2662,2701,2704,2710,2715,2728,2733,2766,2771,2789,2801,2804,2810,2823,2828,2859,2864,2887,2893,2898,2903,2921,2942,2945,2951,2957,2962,2973,2978,2989,2994,3012,3018,3027,3032,3050,3053,3059,3064,3100,3105,3114,3123,3132,3137,3155,3158,3164,3169,3180,3186,3191,3204,3213,3219,3232,3237,3243,3248,3253,3285,3291,3296,3317,3323,3328,3332,3345,3348,3354,3359,3364,3397,3403,3427,3432,3456,3467,3472,3477,3490,3493,3499,3513,3518,3536,3542,3547,3565,3570,3573,3579,3597,3602,3605,3611,3616,3674,3677,3683,3688],{"type":27,"tag":28,"props":2630,"children":2632},{"id":2631},"server-actions-完整指南",[2633],{"type":33,"value":2619},{"type":27,"tag":36,"props":2635,"children":2636},{},[2637,2639,2644],{"type":33,"value":2638},"Server Actions 是 Next.js（App Router 体系）里最有“范式转移”意味的能力之一：它把“从浏览器提交数据 → 走 API → 服务端写库 → 客户端再拉取数据”这条链路，压缩成",{"type":27,"tag":646,"props":2640,"children":2641},{},[2642],{"type":33,"value":2643},"在 UI 里直接调用一个服务端函数",{"type":33,"value":652},{"type":27,"tag":36,"props":2646,"children":2647},{},[2648,2650,2655],{"type":33,"value":2649},"但它并不是“把后端写进前端”，而是一套围绕 ",{"type":27,"tag":646,"props":2651,"children":2652},{},[2653],{"type":33,"value":2654},"RSC（React Server Components）边界、请求序列化、缓存与失效、安全隔离",{"type":33,"value":2656}," 重新定义的交互协议。",{"type":27,"tag":36,"props":2658,"children":2659},{},[2660],{"type":33,"value":2661},"这篇文章按“能在生产落地”为标准，依次讲清：",{"type":27,"tag":47,"props":2663,"children":2664},{},[2665,2670,2681,2686,2691,2696],{"type":27,"tag":51,"props":2666,"children":2667},{},[2668],{"type":33,"value":2669},"什么时候该用/不该用 Server Actions",{"type":27,"tag":51,"props":2671,"children":2672},{},[2673,2679],{"type":27,"tag":830,"props":2674,"children":2676},{"className":2675},[],[2677],{"type":33,"value":2678},"'use server'",{"type":33,"value":2680}," 的语义与编译期边界",{"type":27,"tag":51,"props":2682,"children":2683},{},[2684],{"type":33,"value":2685},"表单提交、并发与幂等",{"type":27,"tag":51,"props":2687,"children":2688},{},[2689],{"type":33,"value":2690},"权限、校验、CSRF/重放、敏感信息",{"type":27,"tag":51,"props":2692,"children":2693},{},[2694],{"type":33,"value":2695},"缓存与 revalidate 的正确打开方式",{"type":27,"tag":51,"props":2697,"children":2698},{},[2699],{"type":33,"value":2700},"一套可复用的工程化结构（Action 层、schema、错误码）",{"type":27,"tag":705,"props":2702,"children":2703},{},[],{"type":27,"tag":28,"props":2705,"children":2707},{"id":2706},"_1-server-actions-解决的到底是什么问题",[2708],{"type":33,"value":2709},"1. Server Actions 解决的到底是什么问题？",{"type":27,"tag":36,"props":2711,"children":2712},{},[2713],{"type":33,"value":2714},"在传统前端架构里，“写操作”通常需要两套代码：",{"type":27,"tag":215,"props":2716,"children":2717},{},[2718,2723],{"type":27,"tag":51,"props":2719,"children":2720},{},[2721],{"type":33,"value":2722},"UI 层构造请求（fetch/axios）",{"type":27,"tag":51,"props":2724,"children":2725},{},[2726],{"type":33,"value":2727},"API 层解析请求、校验、执行业务",{"type":27,"tag":36,"props":2729,"children":2730},{},[2731],{"type":33,"value":2732},"这导致三个常见痛点：",{"type":27,"tag":47,"props":2734,"children":2735},{},[2736,2746,2756],{"type":27,"tag":51,"props":2737,"children":2738},{},[2739,2744],{"type":27,"tag":646,"props":2740,"children":2741},{},[2742],{"type":33,"value":2743},"样板代码多",{"type":33,"value":2745},"：DTO、路由、controller、错误映射",{"type":27,"tag":51,"props":2747,"children":2748},{},[2749,2754],{"type":27,"tag":646,"props":2750,"children":2751},{},[2752],{"type":33,"value":2753},"类型不一致",{"type":33,"value":2755},"：前后端 schema 漂移，靠约定或手写 types",{"type":27,"tag":51,"props":2757,"children":2758},{},[2759,2764],{"type":27,"tag":646,"props":2760,"children":2761},{},[2762],{"type":33,"value":2763},"缓存/失效复杂",{"type":33,"value":2765},"：写完数据后，页面该怎么更新？哪些缓存该失效？",{"type":27,"tag":36,"props":2767,"children":2768},{},[2769],{"type":33,"value":2770},"Server Actions 的核心价值是：",{"type":27,"tag":47,"props":2772,"children":2773},{},[2774,2784],{"type":27,"tag":51,"props":2775,"children":2776},{},[2777,2782],{"type":27,"tag":646,"props":2778,"children":2779},{},[2780],{"type":33,"value":2781},"把“写操作”收敛成一个服务端函数",{"type":33,"value":2783},"，由框架负责把调用从 client 路由到 server；",{"type":27,"tag":51,"props":2785,"children":2786},{},[2787],{"type":33,"value":2788},"在 App Router 的缓存语义下，提供与页面缓存/请求缓存更一致的“失效”手段。",{"type":27,"tag":36,"props":2790,"children":2791},{},[2792,2794,2799],{"type":33,"value":2793},"你可以把它理解为：Next.js 给“写操作”提供了一个",{"type":27,"tag":646,"props":2795,"children":2796},{},[2797],{"type":33,"value":2798},"与 RSC/缓存模型原生兼容",{"type":33,"value":2800},"的调用入口。",{"type":27,"tag":705,"props":2802,"children":2803},{},[],{"type":27,"tag":28,"props":2805,"children":2807},{"id":2806},"_2-心智模型server-actions-与-rsc-的边界",[2808],{"type":33,"value":2809},"2. 心智模型：Server Actions 与 RSC 的边界",{"type":27,"tag":519,"props":2811,"children":2813},{"id":2812},"_21-use-server-不是运行时开关而是编译期边界",[2814,2816,2821],{"type":33,"value":2815},"2.1 ",{"type":27,"tag":830,"props":2817,"children":2819},{"className":2818},[],[2820],{"type":33,"value":2678},{"type":33,"value":2822}," 不是运行时开关，而是编译期边界",{"type":27,"tag":36,"props":2824,"children":2825},{},[2826],{"type":33,"value":2827},"在 Next.js 中：",{"type":27,"tag":47,"props":2829,"children":2830},{},[2831,2854],{"type":27,"tag":51,"props":2832,"children":2833},{},[2834,2840,2841,2846,2848,2853],{"type":27,"tag":830,"props":2835,"children":2837},{"className":2836},[],[2838],{"type":33,"value":2839},"'use client'",{"type":33,"value":837},{"type":27,"tag":830,"props":2842,"children":2844},{"className":2843},[],[2845],{"type":33,"value":2678},{"type":33,"value":2847}," 是",{"type":27,"tag":646,"props":2849,"children":2850},{},[2851],{"type":33,"value":2852},"模块级/函数级的编译指令",{"type":33,"value":652},{"type":27,"tag":51,"props":2855,"children":2856},{},[2857],{"type":33,"value":2858},"被标记为 Server Action 的函数只能在服务端执行；在客户端调用时，框架会生成一个“可调用的引用”，最终由服务端执行。",{"type":27,"tag":36,"props":2860,"children":2861},{},[2862],{"type":33,"value":2863},"一个直观的理解：",{"type":27,"tag":47,"props":2865,"children":2866},{},[2867,2877],{"type":27,"tag":51,"props":2868,"children":2869},{},[2870,2875],{"type":27,"tag":646,"props":2871,"children":2872},{},[2873],{"type":33,"value":2874},"你写的是函数",{"type":33,"value":2876},"；",{"type":27,"tag":51,"props":2878,"children":2879},{},[2880,2885],{"type":27,"tag":646,"props":2881,"children":2882},{},[2883],{"type":33,"value":2884},"框架生成的是 RPC",{"type":33,"value":2886},"（带序列化、鉴权/上下文、执行、返回）。",{"type":27,"tag":519,"props":2888,"children":2890},{"id":2889},"_22-传参限制可序列化是第一原则",[2891],{"type":33,"value":2892},"2.2 传参限制：可序列化是第一原则",{"type":27,"tag":36,"props":2894,"children":2895},{},[2896],{"type":33,"value":2897},"Server Action 的参数需要能安全序列化。",{"type":27,"tag":36,"props":2899,"children":2900},{},[2901],{"type":33,"value":2902},"建议遵循：",{"type":27,"tag":47,"props":2904,"children":2905},{},[2906,2916],{"type":27,"tag":51,"props":2907,"children":2908},{},[2909,2911],{"type":33,"value":2910},"只传 ",{"type":27,"tag":646,"props":2912,"children":2913},{},[2914],{"type":33,"value":2915},"primitive / plain object / array / FormData",{"type":27,"tag":51,"props":2917,"children":2918},{},[2919],{"type":33,"value":2920},"不传 class 实例、函数、DOM 节点、复杂原型对象",{"type":27,"tag":36,"props":2922,"children":2923},{},[2924,2926,2932,2934,2940],{"type":33,"value":2925},"如果你发现自己想把“整个业务对象”丢进去，通常意味着你应该传一个 ",{"type":27,"tag":830,"props":2927,"children":2929},{"className":2928},[],[2930],{"type":33,"value":2931},"id",{"type":33,"value":2933}," 或 ",{"type":27,"tag":830,"props":2935,"children":2937},{"className":2936},[],[2938],{"type":33,"value":2939},"payload",{"type":33,"value":2941},"，然后在服务端再查询/校验。",{"type":27,"tag":705,"props":2943,"children":2944},{},[],{"type":27,"tag":28,"props":2946,"children":2948},{"id":2947},"_3-两种主流用法表单-action-与事件-action",[2949],{"type":33,"value":2950},"3. 两种主流用法：表单 Action 与事件 Action",{"type":27,"tag":519,"props":2952,"children":2954},{"id":2953},"_31-表单提交推荐天然-csrf-友好契合-web-标准",[2955],{"type":33,"value":2956},"3.1 表单提交（推荐）：天然 CSRF 友好，契合 Web 标准",{"type":27,"tag":36,"props":2958,"children":2959},{},[2960],{"type":33,"value":2961},"Server Actions 最推荐的入口是表单：",{"type":27,"tag":900,"props":2963,"children":2968},{"className":2964,"code":2966,"language":2967,"meta":7},[2965],"language-tsx","// app/settings/page.tsx\nimport { updateProfileAction } from './actions'\n\nexport default function SettingsPage() {\n  return (\n    \u003Cform action={updateProfileAction}>\n      \u003Cinput name=\"displayName\" />\n      \u003Cbutton type=\"submit\">保存\u003C/button>\n    \u003C/form>\n  )\n}\n","tsx",[2969],{"type":27,"tag":830,"props":2970,"children":2971},{"__ignoreMap":7},[2972],{"type":33,"value":2966},{"type":27,"tag":36,"props":2974,"children":2975},{},[2976],{"type":33,"value":2977},"在服务端：",{"type":27,"tag":900,"props":2979,"children":2984},{"className":2980,"code":2982,"language":2983,"meta":7},[2981],"language-ts","// app/settings/actions.ts\n'use server'\n\nexport async function updateProfileAction(formData: FormData) {\n  const displayName = String(formData.get('displayName') || '').trim()\n  // 校验、鉴权、写库...\n}\n","ts",[2985],{"type":27,"tag":830,"props":2986,"children":2987},{"__ignoreMap":7},[2988],{"type":33,"value":2982},{"type":27,"tag":36,"props":2990,"children":2991},{},[2992],{"type":33,"value":2993},"为什么推荐表单？",{"type":27,"tag":47,"props":2995,"children":2996},{},[2997,3002,3007],{"type":27,"tag":51,"props":2998,"children":2999},{},[3000],{"type":33,"value":3001},"浏览器原生语义：回退/刷新更自然",{"type":27,"tag":51,"props":3003,"children":3004},{},[3005],{"type":33,"value":3006},"你更容易把“输入 → 校验 → 保存”做成明确的流水线",{"type":27,"tag":51,"props":3008,"children":3009},{},[3010],{"type":33,"value":3011},"比“按钮 onClick 调 action”更不容易写出隐式并发 bug",{"type":27,"tag":519,"props":3013,"children":3015},{"id":3014},"_32-事件触发慎用更像-rpc必须处理并发与幂等",[3016],{"type":33,"value":3017},"3.2 事件触发（慎用）：更像 RPC，必须处理并发与幂等",{"type":27,"tag":900,"props":3019,"children":3022},{"className":3020,"code":3021,"language":2967,"meta":7},[2965],"'use client'\nimport { toggleStarAction } from './actions'\n\nexport function StarButton({ id }: { id: string }) {\n  return (\n    \u003Cbutton\n      onClick={async () => {\n        await toggleStarAction(id)\n      }}\n    >\n      Star\n    \u003C/button>\n  )\n}\n",[3023],{"type":27,"tag":830,"props":3024,"children":3025},{"__ignoreMap":7},[3026],{"type":33,"value":3021},{"type":27,"tag":36,"props":3028,"children":3029},{},[3030],{"type":33,"value":3031},"这类用法更像“客户端发起 RPC”，你需要格外注意：",{"type":27,"tag":47,"props":3033,"children":3034},{},[3035,3040,3045],{"type":27,"tag":51,"props":3036,"children":3037},{},[3038],{"type":33,"value":3039},"重复点击导致并发",{"type":27,"tag":51,"props":3041,"children":3042},{},[3043],{"type":33,"value":3044},"网络抖动导致重试",{"type":27,"tag":51,"props":3046,"children":3047},{},[3048],{"type":33,"value":3049},"乐观更新与最终一致",{"type":27,"tag":705,"props":3051,"children":3052},{},[],{"type":27,"tag":28,"props":3054,"children":3056},{"id":3055},"_4-工程化落地action-层应该长什么样",[3057],{"type":33,"value":3058},"4. 工程化落地：Action 层应该长什么样？",{"type":27,"tag":36,"props":3060,"children":3061},{},[3062],{"type":33,"value":3063},"一个能长期维护的结构，通常把“Action 的对外接口”与“业务实现”分离：",{"type":27,"tag":47,"props":3065,"children":3066},{},[3067,3078,3089],{"type":27,"tag":51,"props":3068,"children":3069},{},[3070,3076],{"type":27,"tag":830,"props":3071,"children":3073},{"className":3072},[],[3074],{"type":33,"value":3075},"actions/*.ts",{"type":33,"value":3077},"：只负责输入解析、校验、鉴权、错误映射、触发失效",{"type":27,"tag":51,"props":3079,"children":3080},{},[3081,3087],{"type":27,"tag":830,"props":3082,"children":3084},{"className":3083},[],[3085],{"type":33,"value":3086},"services/*.ts",{"type":33,"value":3088},"：纯业务逻辑（可被 API/任务队列复用）",{"type":27,"tag":51,"props":3090,"children":3091},{},[3092,3098],{"type":27,"tag":830,"props":3093,"children":3095},{"className":3094},[],[3096],{"type":33,"value":3097},"schemas/*.ts",{"type":33,"value":3099},"：输入 schema（建议用 zod 或你们统一的校验工具）",{"type":27,"tag":36,"props":3101,"children":3102},{},[3103],{"type":33,"value":3104},"示例：",{"type":27,"tag":900,"props":3106,"children":3109},{"className":3107,"code":3108,"language":2983,"meta":7},[2981],"// app/settings/schemas.ts\nimport { z } from 'zod'\n\nexport const updateProfileSchema = z.object({\n  displayName: z.string().min(2).max(32),\n})\n",[3110],{"type":27,"tag":830,"props":3111,"children":3112},{"__ignoreMap":7},[3113],{"type":33,"value":3108},{"type":27,"tag":900,"props":3115,"children":3118},{"className":3116,"code":3117,"language":2983,"meta":7},[2981],"// app/settings/services.ts\nexport async function updateProfile(userId: string, input: { displayName: string }) {\n  // 写库、写缓存、发事件...\n}\n",[3119],{"type":27,"tag":830,"props":3120,"children":3121},{"__ignoreMap":7},[3122],{"type":33,"value":3117},{"type":27,"tag":900,"props":3124,"children":3127},{"className":3125,"code":3126,"language":2983,"meta":7},[2981],"// app/settings/actions.ts\n'use server'\n\nimport { updateProfileSchema } from './schemas'\nimport { updateProfile } from './services'\nimport { revalidatePath } from 'next/cache'\n\nclass ActionError extends Error {\n  code: string\n  constructor(code: string, message: string) {\n    super(message)\n    this.code = code\n  }\n}\n\nfunction requireUserId(): string {\n  // 伪代码：从会话中拿 user\n  // const user = await auth()\n  // if (!user) throw new ActionError('UNAUTHORIZED', '请先登录')\n  return 'user_123'\n}\n\nexport async function updateProfileAction(formData: FormData) {\n  const userId = requireUserId()\n\n  const input = {\n    displayName: String(formData.get('displayName') || '').trim(),\n  }\n\n  const parsed = updateProfileSchema.safeParse(input)\n  if (!parsed.success) {\n    throw new ActionError('VALIDATION_ERROR', '输入不合法')\n  }\n\n  await updateProfile(userId, parsed.data)\n\n  // 关键：写操作后做缓存失效\n  revalidatePath('/settings')\n}\n",[3128],{"type":27,"tag":830,"props":3129,"children":3130},{"__ignoreMap":7},[3131],{"type":33,"value":3126},{"type":27,"tag":36,"props":3133,"children":3134},{},[3135],{"type":33,"value":3136},"这个结构的好处：",{"type":27,"tag":47,"props":3138,"children":3139},{},[3140,3145,3150],{"type":27,"tag":51,"props":3141,"children":3142},{},[3143],{"type":33,"value":3144},"Action 层是“协议适配器”，服务层是“领域逻辑”",{"type":27,"tag":51,"props":3146,"children":3147},{},[3148],{"type":33,"value":3149},"输入校验与鉴权在入口处统一完成",{"type":27,"tag":51,"props":3151,"children":3152},{},[3153],{"type":33,"value":3154},"缓存失效在入口处统一声明",{"type":27,"tag":705,"props":3156,"children":3157},{},[],{"type":27,"tag":28,"props":3159,"children":3161},{"id":3160},"_5-安全边界你必须明确回答的-5-个问题",[3162],{"type":33,"value":3163},"5. 安全边界：你必须明确回答的 5 个问题",{"type":27,"tag":36,"props":3165,"children":3166},{},[3167],{"type":33,"value":3168},"Server Actions 容易让人产生错觉：“既然在 server 执行，那就是安全的”。",{"type":27,"tag":36,"props":3170,"children":3171},{},[3172,3174,3179],{"type":33,"value":3173},"更准确的说法是：",{"type":27,"tag":646,"props":3175,"children":3176},{},[3177],{"type":33,"value":3178},"Server Actions 让调用路径更短，但安全问题一个都不会消失",{"type":33,"value":652},{"type":27,"tag":519,"props":3181,"children":3183},{"id":3182},"_51-认证action-里必须做鉴权",[3184],{"type":33,"value":3185},"5.1 认证：Action 里必须做鉴权",{"type":27,"tag":36,"props":3187,"children":3188},{},[3189],{"type":33,"value":3190},"不要假设“只有页面能调用它”。",{"type":27,"tag":47,"props":3192,"children":3193},{},[3194,3199],{"type":27,"tag":51,"props":3195,"children":3196},{},[3197],{"type":33,"value":3198},"攻击者可以构造请求直接触发 action",{"type":27,"tag":51,"props":3200,"children":3201},{},[3202],{"type":33,"value":3203},"也可能通过 XSS / 依赖污染从客户端触发",{"type":27,"tag":36,"props":3205,"children":3206},{},[3207,3208],{"type":33,"value":968},{"type":27,"tag":646,"props":3209,"children":3210},{},[3211],{"type":33,"value":3212},"每个会修改数据的 action，都要在服务端检查身份与权限。",{"type":27,"tag":519,"props":3214,"children":3216},{"id":3215},"_52-输入校验永远不要信任-formdata",[3217],{"type":33,"value":3218},"5.2 输入校验：永远不要信任 FormData",{"type":27,"tag":47,"props":3220,"children":3221},{},[3222,3227],{"type":27,"tag":51,"props":3223,"children":3224},{},[3225],{"type":33,"value":3226},"字段缺失、空字符串、超长、类型错",{"type":27,"tag":51,"props":3228,"children":3229},{},[3230],{"type":33,"value":3231},"业务约束（例如“昵称不得包含敏感词”）",{"type":27,"tag":36,"props":3233,"children":3234},{},[3235],{"type":33,"value":3236},"建议：用 schema 校验（zod）或你们统一的 validator。",{"type":27,"tag":519,"props":3238,"children":3240},{"id":3239},"_53-幂等与重放写操作要能承受重复执行",[3241],{"type":33,"value":3242},"5.3 幂等与重放：写操作要能承受重复执行",{"type":27,"tag":36,"props":3244,"children":3245},{},[3246],{"type":33,"value":3247},"浏览器/网络层可能导致重复提交。",{"type":27,"tag":36,"props":3249,"children":3250},{},[3251],{"type":33,"value":3252},"常见策略：",{"type":27,"tag":47,"props":3254,"children":3255},{},[3256,3267,3280],{"type":27,"tag":51,"props":3257,"children":3258},{},[3259,3261],{"type":33,"value":3260},"业务幂等键：",{"type":27,"tag":830,"props":3262,"children":3264},{"className":3263},[],[3265],{"type":33,"value":3266},"idempotencyKey",{"type":27,"tag":51,"props":3268,"children":3269},{},[3270,3272,3278],{"type":33,"value":3271},"数据层唯一约束：例如 ",{"type":27,"tag":830,"props":3273,"children":3275},{"className":3274},[],[3276],{"type":33,"value":3277},"(userId, itemId)",{"type":33,"value":3279}," 唯一",{"type":27,"tag":51,"props":3281,"children":3282},{},[3283],{"type":33,"value":3284},"事务：确保写入一致",{"type":27,"tag":519,"props":3286,"children":3288},{"id":3287},"_54-csrf优先走-form-action并启用-same-site-策略",[3289],{"type":33,"value":3290},"5.4 CSRF：优先走 form action，并启用 same-site 策略",{"type":27,"tag":36,"props":3292,"children":3293},{},[3294],{"type":33,"value":3295},"Server Actions 不等于“自动免疫 CSRF”。",{"type":27,"tag":47,"props":3297,"children":3298},{},[3299,3304],{"type":27,"tag":51,"props":3300,"children":3301},{},[3302],{"type":33,"value":3303},"如果你依赖 cookie 会话，仍要考虑跨站请求",{"type":27,"tag":51,"props":3305,"children":3306},{},[3307,3309,3315],{"type":33,"value":3308},"form action 的默认行为更符合浏览器标准，但你仍需要正确配置 cookie 的 ",{"type":27,"tag":830,"props":3310,"children":3312},{"className":3311},[],[3313],{"type":33,"value":3314},"SameSite",{"type":33,"value":3316}," 和 token",{"type":27,"tag":519,"props":3318,"children":3320},{"id":3319},"_55-错误回传不要把内部错误直接暴露给用户",[3321],{"type":33,"value":3322},"5.5 错误回传：不要把内部错误直接暴露给用户",{"type":27,"tag":36,"props":3324,"children":3325},{},[3326],{"type":33,"value":3327},"Action 抛出的错误最终会影响 UI。",{"type":27,"tag":36,"props":3329,"children":3330},{},[3331],{"type":33,"value":1105},{"type":27,"tag":47,"props":3333,"children":3334},{},[3335,3340],{"type":27,"tag":51,"props":3336,"children":3337},{},[3338],{"type":33,"value":3339},"对用户展示：可理解的、稳定的错误码/文案",{"type":27,"tag":51,"props":3341,"children":3342},{},[3343],{"type":33,"value":3344},"对服务端记录：完整 stack、请求上下文、userId、traceId",{"type":27,"tag":705,"props":3346,"children":3347},{},[],{"type":27,"tag":28,"props":3349,"children":3351},{"id":3350},"_6-缓存语义写操作之后页面为什么不更新",[3352],{"type":33,"value":3353},"6. 缓存语义：写操作之后，页面为什么不更新？",{"type":27,"tag":36,"props":3355,"children":3356},{},[3357],{"type":33,"value":3358},"在 App Router 模型里，“看起来像 SSR 的页面”实际上可能被缓存。",{"type":27,"tag":36,"props":3360,"children":3361},{},[3362],{"type":33,"value":3363},"你需要掌握 3 个概念：",{"type":27,"tag":47,"props":3365,"children":3366},{},[3367,3377,3387],{"type":27,"tag":51,"props":3368,"children":3369},{},[3370,3375],{"type":27,"tag":646,"props":3371,"children":3372},{},[3373],{"type":33,"value":3374},"请求缓存",{"type":33,"value":3376},"（fetch cache）",{"type":27,"tag":51,"props":3378,"children":3379},{},[3380,3385],{"type":27,"tag":646,"props":3381,"children":3382},{},[3383],{"type":33,"value":3384},"页面/路由段缓存",{"type":33,"value":3386},"（RSC payload cache）",{"type":27,"tag":51,"props":3388,"children":3389},{},[3390,3395],{"type":27,"tag":646,"props":3391,"children":3392},{},[3393],{"type":33,"value":3394},"失效机制",{"type":33,"value":3396},"（revalidatePath / revalidateTag）",{"type":27,"tag":519,"props":3398,"children":3400},{"id":3399},"_61-写操作后推荐怎么做",[3401],{"type":33,"value":3402},"6.1 写操作后，推荐怎么做？",{"type":27,"tag":47,"props":3404,"children":3405},{},[3406,3416],{"type":27,"tag":51,"props":3407,"children":3408},{},[3409,3411],{"type":33,"value":3410},"更新某个页面：",{"type":27,"tag":830,"props":3412,"children":3414},{"className":3413},[],[3415],{"type":33,"value":1221},{"type":27,"tag":51,"props":3417,"children":3418},{},[3419,3421],{"type":33,"value":3420},"更新多个数据源：给 fetch 打 tag，然后 ",{"type":27,"tag":830,"props":3422,"children":3424},{"className":3423},[],[3425],{"type":33,"value":3426},"revalidateTag('tag-name')",{"type":27,"tag":36,"props":3428,"children":3429},{},[3430],{"type":33,"value":3431},"建议的经验法则：",{"type":27,"tag":47,"props":3433,"children":3434},{},[3435,3446],{"type":27,"tag":51,"props":3436,"children":3437},{},[3438,3440],{"type":33,"value":3439},"页面级别更新不多：优先 ",{"type":27,"tag":830,"props":3441,"children":3443},{"className":3442},[],[3444],{"type":33,"value":3445},"revalidatePath",{"type":27,"tag":51,"props":3447,"children":3448},{},[3449,3451],{"type":33,"value":3450},"数据在多个页面复用：优先 ",{"type":27,"tag":830,"props":3452,"children":3454},{"className":3453},[],[3455],{"type":33,"value":630},{"type":27,"tag":519,"props":3457,"children":3459},{"id":3458},"_62-不要滥用-revalidatepath",[3460,3462],{"type":33,"value":3461},"6.2 不要滥用 ",{"type":27,"tag":830,"props":3463,"children":3465},{"className":3464},[],[3466],{"type":33,"value":1375},{"type":27,"tag":36,"props":3468,"children":3469},{},[3470],{"type":33,"value":3471},"这会让你的缓存命中率断崖式下降。",{"type":27,"tag":36,"props":3473,"children":3474},{},[3475],{"type":33,"value":3476},"更好的做法：",{"type":27,"tag":47,"props":3478,"children":3479},{},[3480,3485],{"type":27,"tag":51,"props":3481,"children":3482},{},[3483],{"type":33,"value":3484},"只失效受影响的 route segment",{"type":27,"tag":51,"props":3486,"children":3487},{},[3488],{"type":33,"value":3489},"用 tag 精准失效",{"type":27,"tag":705,"props":3491,"children":3492},{},[],{"type":27,"tag":28,"props":3494,"children":3496},{"id":3495},"_7-并发与用户体验让-action-看起来快而可靠",[3497],{"type":33,"value":3498},"7. 并发与用户体验：让 Action 看起来“快而可靠”",{"type":27,"tag":519,"props":3500,"children":3502},{"id":3501},"_71-usetransition-与-pending-状态",[3503,3505,3511],{"type":33,"value":3504},"7.1 ",{"type":27,"tag":830,"props":3506,"children":3508},{"className":3507},[],[3509],{"type":33,"value":3510},"useTransition",{"type":33,"value":3512}," 与 Pending 状态",{"type":27,"tag":36,"props":3514,"children":3515},{},[3516],{"type":33,"value":3517},"当 action 触发后，用户需要看到明确反馈。",{"type":27,"tag":47,"props":3519,"children":3520},{},[3521,3526,3531],{"type":27,"tag":51,"props":3522,"children":3523},{},[3524],{"type":33,"value":3525},"按钮 loading",{"type":27,"tag":51,"props":3527,"children":3528},{},[3529],{"type":33,"value":3530},"禁用重复提交",{"type":27,"tag":51,"props":3532,"children":3533},{},[3534],{"type":33,"value":3535},"成功/失败 toast",{"type":27,"tag":519,"props":3537,"children":3539},{"id":3538},"_72-乐观更新谨慎",[3540],{"type":33,"value":3541},"7.2 乐观更新（谨慎）",{"type":27,"tag":36,"props":3543,"children":3544},{},[3545],{"type":33,"value":3546},"乐观更新适合：",{"type":27,"tag":47,"props":3548,"children":3549},{},[3550,3555,3560],{"type":27,"tag":51,"props":3551,"children":3552},{},[3553],{"type":33,"value":3554},"可快速回滚",{"type":27,"tag":51,"props":3556,"children":3557},{},[3558],{"type":33,"value":3559},"失败概率低",{"type":27,"tag":51,"props":3561,"children":3562},{},[3563],{"type":33,"value":3564},"用户对即时反馈敏感（点赞/收藏）",{"type":27,"tag":36,"props":3566,"children":3567},{},[3568],{"type":33,"value":3569},"对“资金/权限/关键数据”写操作不建议乐观更新。",{"type":27,"tag":705,"props":3571,"children":3572},{},[],{"type":27,"tag":28,"props":3574,"children":3576},{"id":3575},"_8-什么时候不该用-server-actions",[3577],{"type":33,"value":3578},"8. 什么时候不该用 Server Actions？",{"type":27,"tag":47,"props":3580,"children":3581},{},[3582,3587,3592],{"type":27,"tag":51,"props":3583,"children":3584},{},[3585],{"type":33,"value":3586},"需要对外开放的公共 API（给第三方/移动端）",{"type":27,"tag":51,"props":3588,"children":3589},{},[3590],{"type":33,"value":3591},"需要长时间运行的任务（应改为队列/异步任务）",{"type":27,"tag":51,"props":3593,"children":3594},{},[3595],{"type":33,"value":3596},"需要复杂流控/网关策略（限流、WAF、跨服务认证）",{"type":27,"tag":36,"props":3598,"children":3599},{},[3600],{"type":33,"value":3601},"Server Actions 是“Web 应用内的写操作入口”，不是 API 网关替代品。",{"type":27,"tag":705,"props":3603,"children":3604},{},[],{"type":27,"tag":28,"props":3606,"children":3608},{"id":3607},"_9-生产级检查清单",[3609],{"type":33,"value":3610},"9. 生产级检查清单",{"type":27,"tag":36,"props":3612,"children":3613},{},[3614],{"type":33,"value":3615},"在把某个写操作迁移到 Server Actions 前，按这份清单过一遍：",{"type":27,"tag":47,"props":3617,"children":3619},{"className":3618},[434],[3620,3629,3638,3647,3656,3665],{"type":27,"tag":51,"props":3621,"children":3623},{"className":3622},[439],[3624,3627],{"type":27,"tag":442,"props":3625,"children":3626},{"disabled":444,"type":445},[],{"type":33,"value":3628}," action 是否做了鉴权与权限校验",{"type":27,"tag":51,"props":3630,"children":3632},{"className":3631},[439],[3633,3636],{"type":27,"tag":442,"props":3634,"children":3635},{"disabled":444,"type":445},[],{"type":33,"value":3637}," 输入是否做了 schema 校验",{"type":27,"tag":51,"props":3639,"children":3641},{"className":3640},[439],[3642,3645],{"type":27,"tag":442,"props":3643,"children":3644},{"disabled":444,"type":445},[],{"type":33,"value":3646}," 是否具备幂等策略（或数据层唯一约束）",{"type":27,"tag":51,"props":3648,"children":3650},{"className":3649},[439],[3651,3654],{"type":27,"tag":442,"props":3652,"children":3653},{"disabled":444,"type":445},[],{"type":33,"value":3655}," 是否定义了稳定的错误码/文案",{"type":27,"tag":51,"props":3657,"children":3659},{"className":3658},[439],[3660,3663],{"type":27,"tag":442,"props":3661,"children":3662},{"disabled":444,"type":445},[],{"type":33,"value":3664}," 写操作后是否做了精确的缓存失效（path/tag）",{"type":27,"tag":51,"props":3666,"children":3668},{"className":3667},[439],[3669,3672],{"type":27,"tag":442,"props":3670,"children":3671},{"disabled":444,"type":445},[],{"type":33,"value":3673}," 是否有可观测性：日志、traceId、错误上报",{"type":27,"tag":705,"props":3675,"children":3676},{},[],{"type":27,"tag":28,"props":3678,"children":3680},{"id":3679},"_10-总结",[3681],{"type":33,"value":3682},"10. 总结",{"type":27,"tag":36,"props":3684,"children":3685},{},[3686],{"type":33,"value":3687},"Server Actions 的正确价值不是“少写 API”，而是：",{"type":27,"tag":47,"props":3689,"children":3690},{},[3691,3696,3701],{"type":27,"tag":51,"props":3692,"children":3693},{},[3694],{"type":33,"value":3695},"把写操作纳入 App Router/RSC 的统一模型",{"type":27,"tag":51,"props":3697,"children":3698},{},[3699],{"type":33,"value":3700},"让缓存失效与 UI 刷新更一致",{"type":27,"tag":51,"props":3702,"children":3703},{},[3704],{"type":33,"value":3705},"在正确工程结构下，显著减少样板代码与类型漂移",{"title":7,"searchDepth":598,"depth":598,"links":3707},[3708,3709,3710,3715,3719,3720,3727,3732,3737,3738,3739],{"id":2631,"depth":601,"text":2619},{"id":2706,"depth":601,"text":2709},{"id":2806,"depth":601,"text":2809,"children":3711},[3712,3714],{"id":2812,"depth":598,"text":3713},"2.1 'use server' 不是运行时开关，而是编译期边界",{"id":2889,"depth":598,"text":2892},{"id":2947,"depth":601,"text":2950,"children":3716},[3717,3718],{"id":2953,"depth":598,"text":2956},{"id":3014,"depth":598,"text":3017},{"id":3055,"depth":601,"text":3058},{"id":3160,"depth":601,"text":3163,"children":3721},[3722,3723,3724,3725,3726],{"id":3182,"depth":598,"text":3185},{"id":3215,"depth":598,"text":3218},{"id":3239,"depth":598,"text":3242},{"id":3287,"depth":598,"text":3290},{"id":3319,"depth":598,"text":3322},{"id":3350,"depth":601,"text":3353,"children":3728},[3729,3730],{"id":3399,"depth":598,"text":3402},{"id":3458,"depth":598,"text":3731},"6.2 不要滥用 revalidatePath('/')",{"id":3495,"depth":601,"text":3498,"children":3733},[3734,3736],{"id":3501,"depth":598,"text":3735},"7.1 useTransition 与 Pending 状态",{"id":3538,"depth":598,"text":3541},{"id":3575,"depth":601,"text":3578},{"id":3607,"depth":601,"text":3610},{"id":3679,"depth":601,"text":3682},"content:topics:next:server-actions-complete-guide.md","topics/next/server-actions-complete-guide.md","topics/next/server-actions-complete-guide",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"topic":5,"author":11,"tags":3744,"image":18,"imageQuery":19,"pexelsPhotoId":20,"pexelsUrl":21,"featured":6,"readingTime":22,"body":3745,"_type":615,"_id":616,"_source":617,"_file":618,"_stem":619,"_extension":620},[13,14,15,16,17],{"type":24,"children":3746,"toc":4196},[3747,3751,3755,3759,3778,3782,3786,3861,3865,3869,3873,3888,3892,3907,3911,3915,3930,3934,3949,3953,3957,3961,3976,3980,3984,3999,4003,4007,4011,4026,4030,4034,4038,4057,4061,4065,4133,4137,4141,4145,4149,4153,4157,4161,4165],{"type":27,"tag":28,"props":3748,"children":3749},{"id":30},[3750],{"type":33,"value":34},{"type":27,"tag":36,"props":3752,"children":3753},{},[3754],{"type":33,"value":40},{"type":27,"tag":36,"props":3756,"children":3757},{},[3758],{"type":33,"value":45},{"type":27,"tag":47,"props":3760,"children":3761},{},[3762,3766,3770,3774],{"type":27,"tag":51,"props":3763,"children":3764},{},[3765],{"type":33,"value":55},{"type":27,"tag":51,"props":3767,"children":3768},{},[3769],{"type":33,"value":60},{"type":27,"tag":51,"props":3771,"children":3772},{},[3773],{"type":33,"value":65},{"type":27,"tag":51,"props":3775,"children":3776},{},[3777],{"type":33,"value":70},{"type":27,"tag":28,"props":3779,"children":3780},{"id":73},[3781],{"type":33,"value":76},{"type":27,"tag":36,"props":3783,"children":3784},{},[3785],{"type":33,"value":81},{"type":27,"tag":83,"props":3787,"children":3788},{},[3789,3803],{"type":27,"tag":87,"props":3790,"children":3791},{},[3792],{"type":27,"tag":91,"props":3793,"children":3794},{},[3795,3799],{"type":27,"tag":95,"props":3796,"children":3797},{},[3798],{"type":33,"value":99},{"type":27,"tag":95,"props":3800,"children":3801},{},[3802],{"type":33,"value":104},{"type":27,"tag":106,"props":3804,"children":3805},{},[3806,3817,3828,3839,3850],{"type":27,"tag":91,"props":3807,"children":3808},{},[3809,3813],{"type":27,"tag":113,"props":3810,"children":3811},{},[3812],{"type":33,"value":117},{"type":27,"tag":113,"props":3814,"children":3815},{},[3816],{"type":33,"value":122},{"type":27,"tag":91,"props":3818,"children":3819},{},[3820,3824],{"type":27,"tag":113,"props":3821,"children":3822},{},[3823],{"type":33,"value":130},{"type":27,"tag":113,"props":3825,"children":3826},{},[3827],{"type":33,"value":135},{"type":27,"tag":91,"props":3829,"children":3830},{},[3831,3835],{"type":27,"tag":113,"props":3832,"children":3833},{},[3834],{"type":33,"value":143},{"type":27,"tag":113,"props":3836,"children":3837},{},[3838],{"type":33,"value":148},{"type":27,"tag":91,"props":3840,"children":3841},{},[3842,3846],{"type":27,"tag":113,"props":3843,"children":3844},{},[3845],{"type":33,"value":156},{"type":27,"tag":113,"props":3847,"children":3848},{},[3849],{"type":33,"value":161},{"type":27,"tag":91,"props":3851,"children":3852},{},[3853,3857],{"type":27,"tag":113,"props":3854,"children":3855},{},[3856],{"type":33,"value":169},{"type":27,"tag":113,"props":3858,"children":3859},{},[3860],{"type":33,"value":174},{"type":27,"tag":36,"props":3862,"children":3863},{},[3864],{"type":33,"value":179},{"type":27,"tag":28,"props":3866,"children":3867},{"id":182},[3868],{"type":33,"value":185},{"type":27,"tag":36,"props":3870,"children":3871},{},[3872],{"type":33,"value":190},{"type":27,"tag":47,"props":3874,"children":3875},{},[3876,3880,3884],{"type":27,"tag":51,"props":3877,"children":3878},{},[3879],{"type":33,"value":198},{"type":27,"tag":51,"props":3881,"children":3882},{},[3883],{"type":33,"value":203},{"type":27,"tag":51,"props":3885,"children":3886},{},[3887],{"type":33,"value":208},{"type":27,"tag":36,"props":3889,"children":3890},{},[3891],{"type":33,"value":213},{"type":27,"tag":215,"props":3893,"children":3894},{},[3895,3899,3903],{"type":27,"tag":51,"props":3896,"children":3897},{},[3898],{"type":33,"value":222},{"type":27,"tag":51,"props":3900,"children":3901},{},[3902],{"type":33,"value":227},{"type":27,"tag":51,"props":3904,"children":3905},{},[3906],{"type":33,"value":232},{"type":27,"tag":28,"props":3908,"children":3909},{"id":235},[3910],{"type":33,"value":238},{"type":27,"tag":36,"props":3912,"children":3913},{},[3914],{"type":33,"value":243},{"type":27,"tag":47,"props":3916,"children":3917},{},[3918,3922,3926],{"type":27,"tag":51,"props":3919,"children":3920},{},[3921],{"type":33,"value":251},{"type":27,"tag":51,"props":3923,"children":3924},{},[3925],{"type":33,"value":256},{"type":27,"tag":51,"props":3927,"children":3928},{},[3929],{"type":33,"value":261},{"type":27,"tag":36,"props":3931,"children":3932},{},[3933],{"type":33,"value":266},{"type":27,"tag":47,"props":3935,"children":3936},{},[3937,3941,3945],{"type":27,"tag":51,"props":3938,"children":3939},{},[3940],{"type":33,"value":274},{"type":27,"tag":51,"props":3942,"children":3943},{},[3944],{"type":33,"value":279},{"type":27,"tag":51,"props":3946,"children":3947},{},[3948],{"type":33,"value":284},{"type":27,"tag":36,"props":3950,"children":3951},{},[3952],{"type":33,"value":289},{"type":27,"tag":28,"props":3954,"children":3955},{"id":292},[3956],{"type":33,"value":295},{"type":27,"tag":36,"props":3958,"children":3959},{},[3960],{"type":33,"value":300},{"type":27,"tag":215,"props":3962,"children":3963},{},[3964,3968,3972],{"type":27,"tag":51,"props":3965,"children":3966},{},[3967],{"type":33,"value":308},{"type":27,"tag":51,"props":3969,"children":3970},{},[3971],{"type":33,"value":313},{"type":27,"tag":51,"props":3973,"children":3974},{},[3975],{"type":33,"value":318},{"type":27,"tag":36,"props":3977,"children":3978},{},[3979],{"type":33,"value":323},{"type":27,"tag":36,"props":3981,"children":3982},{},[3983],{"type":33,"value":328},{"type":27,"tag":215,"props":3985,"children":3986},{},[3987,3991,3995],{"type":27,"tag":51,"props":3988,"children":3989},{},[3990],{"type":33,"value":336},{"type":27,"tag":51,"props":3992,"children":3993},{},[3994],{"type":33,"value":341},{"type":27,"tag":51,"props":3996,"children":3997},{},[3998],{"type":33,"value":346},{"type":27,"tag":28,"props":4000,"children":4001},{"id":349},[4002],{"type":33,"value":352},{"type":27,"tag":36,"props":4004,"children":4005},{},[4006],{"type":33,"value":357},{"type":27,"tag":36,"props":4008,"children":4009},{},[4010],{"type":33,"value":362},{"type":27,"tag":47,"props":4012,"children":4013},{},[4014,4018,4022],{"type":27,"tag":51,"props":4015,"children":4016},{},[4017],{"type":33,"value":370},{"type":27,"tag":51,"props":4019,"children":4020},{},[4021],{"type":33,"value":375},{"type":27,"tag":51,"props":4023,"children":4024},{},[4025],{"type":33,"value":380},{"type":27,"tag":36,"props":4027,"children":4028},{},[4029],{"type":33,"value":385},{"type":27,"tag":28,"props":4031,"children":4032},{"id":388},[4033],{"type":33,"value":391},{"type":27,"tag":36,"props":4035,"children":4036},{},[4037],{"type":33,"value":396},{"type":27,"tag":47,"props":4039,"children":4040},{},[4041,4045,4049,4053],{"type":27,"tag":51,"props":4042,"children":4043},{},[4044],{"type":33,"value":404},{"type":27,"tag":51,"props":4046,"children":4047},{},[4048],{"type":33,"value":409},{"type":27,"tag":51,"props":4050,"children":4051},{},[4052],{"type":33,"value":414},{"type":27,"tag":51,"props":4054,"children":4055},{},[4056],{"type":33,"value":419},{"type":27,"tag":36,"props":4058,"children":4059},{},[4060],{"type":33,"value":424},{"type":27,"tag":28,"props":4062,"children":4063},{"id":427},[4064],{"type":33,"value":430},{"type":27,"tag":47,"props":4066,"children":4068},{"className":4067},[434],[4069,4077,4085,4093,4101,4109,4117,4125],{"type":27,"tag":51,"props":4070,"children":4072},{"className":4071},[439],[4073,4076],{"type":27,"tag":442,"props":4074,"children":4075},{"disabled":444,"type":445},[],{"type":33,"value":448},{"type":27,"tag":51,"props":4078,"children":4080},{"className":4079},[439],[4081,4084],{"type":27,"tag":442,"props":4082,"children":4083},{"disabled":444,"type":445},[],{"type":33,"value":457},{"type":27,"tag":51,"props":4086,"children":4088},{"className":4087},[439],[4089,4092],{"type":27,"tag":442,"props":4090,"children":4091},{"disabled":444,"type":445},[],{"type":33,"value":466},{"type":27,"tag":51,"props":4094,"children":4096},{"className":4095},[439],[4097,4100],{"type":27,"tag":442,"props":4098,"children":4099},{"disabled":444,"type":445},[],{"type":33,"value":475},{"type":27,"tag":51,"props":4102,"children":4104},{"className":4103},[439],[4105,4108],{"type":27,"tag":442,"props":4106,"children":4107},{"disabled":444,"type":445},[],{"type":33,"value":484},{"type":27,"tag":51,"props":4110,"children":4112},{"className":4111},[439],[4113,4116],{"type":27,"tag":442,"props":4114,"children":4115},{"disabled":444,"type":445},[],{"type":33,"value":493},{"type":27,"tag":51,"props":4118,"children":4120},{"className":4119},[439],[4121,4124],{"type":27,"tag":442,"props":4122,"children":4123},{"disabled":444,"type":445},[],{"type":33,"value":502},{"type":27,"tag":51,"props":4126,"children":4128},{"className":4127},[439],[4129,4132],{"type":27,"tag":442,"props":4130,"children":4131},{"disabled":444,"type":445},[],{"type":33,"value":511},{"type":27,"tag":28,"props":4134,"children":4135},{"id":514},[4136],{"type":33,"value":517},{"type":27,"tag":519,"props":4138,"children":4139},{"id":521},[4140],{"type":33,"value":524},{"type":27,"tag":36,"props":4142,"children":4143},{},[4144],{"type":33,"value":529},{"type":27,"tag":519,"props":4146,"children":4147},{"id":532},[4148],{"type":33,"value":535},{"type":27,"tag":36,"props":4150,"children":4151},{},[4152],{"type":33,"value":540},{"type":27,"tag":519,"props":4154,"children":4155},{"id":543},[4156],{"type":33,"value":546},{"type":27,"tag":36,"props":4158,"children":4159},{},[4160],{"type":33,"value":551},{"type":27,"tag":28,"props":4162,"children":4163},{"id":554},[4164],{"type":33,"value":554},{"type":27,"tag":47,"props":4166,"children":4167},{},[4168,4175,4182,4189],{"type":27,"tag":51,"props":4169,"children":4170},{},[4171],{"type":27,"tag":564,"props":4172,"children":4173},{"href":566},[4174],{"type":33,"value":569},{"type":27,"tag":51,"props":4176,"children":4177},{},[4178],{"type":27,"tag":564,"props":4179,"children":4180},{"href":575},[4181],{"type":33,"value":578},{"type":27,"tag":51,"props":4183,"children":4184},{},[4185],{"type":27,"tag":564,"props":4186,"children":4187},{"href":584},[4188],{"type":33,"value":587},{"type":27,"tag":51,"props":4190,"children":4191},{},[4192],{"type":27,"tag":564,"props":4193,"children":4194},{"href":593},[4195],{"type":33,"value":596},{"title":7,"searchDepth":598,"depth":598,"links":4197},[4198,4199,4200,4201,4202,4203,4204,4205,4206,4211],{"id":30,"depth":601,"text":34},{"id":73,"depth":601,"text":76},{"id":182,"depth":601,"text":185},{"id":235,"depth":601,"text":238},{"id":292,"depth":601,"text":295},{"id":349,"depth":601,"text":352},{"id":388,"depth":601,"text":391},{"id":427,"depth":601,"text":430},{"id":514,"depth":601,"text":517,"children":4207},[4208,4209,4210],{"id":521,"depth":598,"text":524},{"id":532,"depth":598,"text":535},{"id":543,"depth":598,"text":546},{"id":554,"depth":601,"text":554},1775441242967]