[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"i-ri:search-line":3,"i-ri:moon-line":8,"i-ri:sun-line":10,"i-ri:menu-3-line":12,"i-ri:close-line":14,"notes-module-items-react":16,"notes-page-react-12-rendering-and-delivery\u002F01-hydration-mismatch":494,"i-ri:arrow-left-s-line":3091,"i-ri:menu-2-line":3093,"i-ri:arrow-right-s-line":3095,"i-ep:copy-document":3097},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"currentColor\" d=\"m18.031 16.617l4.283 4.282l-1.415 1.415l-4.282-4.283A8.96 8.96 0 0 1 11 20c-4.968 0-9-4.032-9-9s4.032-9 9-9s9 4.032 9 9a8.96 8.96 0 0 1-1.969 5.617m-2.006-.742A6.98 6.98 0 0 0 18 11c0-3.867-3.133-7-7-7s-7 3.133-7 7s3.133 7 7 7a6.98 6.98 0 0 0 4.875-1.975z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"currentColor\" d=\"M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2h.1A6.98 6.98 0 0 0 10 7m-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938A8 8 0 0 0 4 12\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":11},"\u003Cpath fill=\"currentColor\" d=\"M12 18a6 6 0 1 1 0-12a6 6 0 0 1 0 12m0-2a4 4 0 1 0 0-8a4 4 0 0 0 0 8M11 1h2v3h-2zm0 19h2v3h-2zM3.515 4.929l1.414-1.414L7.05 5.636L5.636 7.05zM16.95 18.364l1.414-1.414l2.121 2.121l-1.414 1.414zm2.121-14.85l1.414 1.415l-2.121 2.121l-1.414-1.414zM5.636 16.95l1.414 1.414l-2.121 2.121l-1.414-1.414zM23 11v2h-3v-2zM4 11v2H1v-2z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":13},"\u003Cpath fill=\"currentColor\" d=\"M3 4h18v2H3zm6 7h12v2H9zm-6 7h18v2H3z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":15},"\u003Cpath fill=\"currentColor\" d=\"m12 10.587l4.95-4.95l1.414 1.414l-4.95 4.95l4.95 4.95l-1.415 1.414l-4.95-4.95l-4.949 4.95l-1.414-1.415l4.95-4.95l-4.95-4.95L7.05 5.638z\"\u002F>",[17,22,26,30,34,38,42,46,50,54,58,62,66,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126,130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,214,218,222,226,230,234,238,242,246,250,254,258,262,266,270,274,278,282,286,290,294,298,302,306,310,314,318,322,326,330,334,338,342,346,350,354,358,362,366,370,374,378,382,386,390,394,398,402,406,410,414,418,422,426,430,434,438,442,446,450,454,458,462,466,470,474,478,482,486,490],{"path":18,"title":19,"meta":20},"\u002Fnotes\u002Freact\u002F01-basics\u002F01-how-to-read-this-repo","如何阅读本仓库（学习路径与章节依赖）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},"2026-11-05T09:47:15.000Z",{"path":23,"title":24,"meta":25},"\u002Fnotes\u002Freact\u002F01-basics\u002F02-render-vs-commit","React 渲染两阶段：Render vs Commit（总览）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":27,"title":28,"meta":29},"\u002Fnotes\u002Freact\u002F01-basics\u002F03-update-pipeline-birdview","从“更新”到“页面变更”：一次 setState 的全链路鸟瞰",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":31,"title":32,"meta":33},"\u002Fnotes\u002Freact\u002F01-basics","基础入门（建议先读）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":35,"title":36,"meta":37},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F01-browser-multi-process","浏览器多进程架构",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":39,"title":40,"meta":41},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F02-event-loop-overview","事件循环概述",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":43,"title":44,"meta":45},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F03-call-stack","函数调用栈",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":47,"title":48,"meta":49},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F04-threads","线程介绍",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":51,"title":52,"meta":53},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F05-refresh-rate-and-queues","刷新率与执行队列",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":55,"title":56,"meta":57},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F06-settimeout","setTimeout 原理详解",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":59,"title":60,"meta":61},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F07-promise","Promise 原理详解",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":63,"title":64,"meta":65},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F08-event-loop-in-practice","事件循环机制（综合）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":67,"title":68,"meta":69},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F09-priority-queues","优先级队列",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":71,"title":72,"meta":73},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F01-concept","并发模式：概念",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":75,"title":76,"meta":77},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F02-demo","案例演示并发模式",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":79,"title":80,"meta":81},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F03-high-priority-preemption","高优先级插队",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":83,"title":84,"meta":85},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F04-preemption-vs-interruption","插队的影响、与中断的区别",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":87,"title":88,"meta":89},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F05-shouldYield","中断条件：shouldYield",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":91,"title":92,"meta":93},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F06-react-tasks-and-queues","React 中的任务与队列",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":95,"title":96,"meta":97},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F07-ensureRootIsScheduled","ensureRootIsScheduled",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":99,"title":100,"meta":101},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F08-batch-updates-merge","合并多个更新触发",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":103,"title":104,"meta":105},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F09-taskQueue-lifecycle","taskQueue 队列循环的启动与结束",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":107,"title":108,"meta":109},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F10-time-slicing","时间切片是如何实现的",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":111,"title":112,"meta":113},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F11-workLoop-full","workLoop 循环完整逻辑",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":115,"title":116,"meta":117},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F12-priority-design","React 中的优先级设计",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":119,"title":120,"meta":121},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F13-lane-model","lane 模型",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":123,"title":124,"meta":125},"\u002Fnotes\u002Freact\u002F04-fiber\u002F01-three-node-types","三种节点对象",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":127,"title":128,"meta":129},"\u002Fnotes\u002Freact\u002F04-fiber\u002F02-fiberRootNode","FiberRootNode",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":131,"title":132,"meta":133},"\u002Fnotes\u002Freact\u002F04-fiber\u002F03-fiber-tree","Fiber 树",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":135,"title":136,"meta":137},"\u002Fnotes\u002Freact\u002F04-fiber\u002F04-initial-mount-build","Fiber 树初始构建过程",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":139,"title":140,"meta":141},"\u002Fnotes\u002Freact\u002F04-fiber\u002F05-workLoopConcurrent","workLoopConcurrent",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":143,"title":144,"meta":145},"\u002Fnotes\u002Freact\u002F04-fiber\u002F06-stack-and-workInProgress","栈结构 与 workInProgress",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":147,"title":148,"meta":149},"\u002Fnotes\u002Freact\u002F04-fiber\u002F07-executionContext","执行上下文 executionContext",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":151,"title":152,"meta":153},"\u002Fnotes\u002Freact\u002F04-fiber\u002F08-update-lanes","update lanes",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":155,"title":156,"meta":157},"\u002Fnotes\u002Freact\u002F04-fiber\u002F09-render-lanes","render lanes",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":159,"title":160,"meta":161},"\u002Fnotes\u002Freact\u002F04-fiber\u002F10-fiber-lanes","fiber lanes",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":163,"title":164,"meta":165},"\u002Fnotes\u002Freact\u002F04-fiber\u002F11-flags-appendix","附录：flags",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":167,"title":168,"meta":169},"\u002Fnotes\u002Freact\u002F05-hooks\u002F01-background","hook 背景",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":171,"title":172,"meta":173},"\u002Fnotes\u002Freact\u002F05-hooks\u002F02-categories","hook 分类",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":175,"title":176,"meta":177},"\u002Fnotes\u002Freact\u002F05-hooks\u002F03-closures","hook 与闭包",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":179,"title":180,"meta":181},"\u002Fnotes\u002Freact\u002F05-hooks\u002F04-hooks-and-fiber","hook 与 fiber",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":183,"title":184,"meta":185},"\u002Fnotes\u002Freact\u002F05-hooks\u002F05-renderWithHooks","renderWithHooks",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":187,"title":188,"meta":189},"\u002Fnotes\u002Freact\u002F05-hooks\u002F06-init-state-hook","初始化 State Hook",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":191,"title":192,"meta":193},"\u002Fnotes\u002Freact\u002F05-hooks\u002F07-init-effect-hook","初始化 effect Hook",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":195,"title":196,"meta":197},"\u002Fnotes\u002Freact\u002F05-hooks\u002F08-circular-linked-list","环形链表详解",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":199,"title":200,"meta":201},"\u002Fnotes\u002Freact\u002F05-hooks\u002F09-useReducer-vs-useState","useReducer 与 useState 的区别",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":203,"title":204,"meta":205},"\u002Fnotes\u002Freact\u002F05-hooks\u002F10-update-linked-list","update 链表",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":207,"title":208,"meta":209},"\u002Fnotes\u002Freact\u002F05-hooks\u002F11-mount-state-updates","初始阶段的状态更新",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":211,"title":212,"meta":213},"\u002Fnotes\u002Freact\u002F05-hooks\u002F12-baseQueue-vs-pending","baseQueue 与 queue.pending",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":215,"title":216,"meta":217},"\u002Fnotes\u002Freact\u002F05-hooks\u002F13-dispatch-in-update","更新阶段的 dispatch",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":219,"title":220,"meta":221},"\u002Fnotes\u002Freact\u002F05-hooks\u002F14-commitRoot","commitRoot",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":223,"title":224,"meta":225},"\u002Fnotes\u002Freact\u002F06-diff\u002F01-update-overview","React 更新机制概述",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":227,"title":228,"meta":229},"\u002Fnotes\u002Freact\u002F06-diff\u002F02-diff-strategy","diff 策略",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":231,"title":232,"meta":233},"\u002Fnotes\u002Freact\u002F06-diff\u002F03-node-compare","节点比较方式",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":235,"title":236,"meta":237},"\u002Fnotes\u002Freact\u002F06-diff\u002F04-reconcileChildFibers","reconcileChildFibers",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":239,"title":240,"meta":241},"\u002Fnotes\u002Freact\u002F06-diff\u002F05-reconcileSingleElement","reconcileSingleElement",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":243,"title":244,"meta":245},"\u002Fnotes\u002Freact\u002F06-diff\u002F06-reconcileChildrenArray","reconcileChildrenArray",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":247,"title":248,"meta":249},"\u002Fnotes\u002Freact\u002F06-diff\u002F07-why-not-number-key","为什么不建议使用数字作为 key",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":251,"title":252,"meta":253},"\u002Fnotes\u002Freact\u002F07-event-system\u002F01-overview","事件系统概述",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":255,"title":256,"meta":257},"\u002Fnotes\u002Freact\u002F07-event-system\u002F02-event-plugin","事件插件",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":259,"title":260,"meta":261},"\u002Fnotes\u002Freact\u002F07-event-system\u002F03-event-pooling","事件池",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":263,"title":264,"meta":265},"\u002Fnotes\u002Freact\u002F07-event-system\u002F04-root-listeners","根节点事件绑定",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":267,"title":268,"meta":269},"\u002Fnotes\u002Freact\u002F07-event-system\u002F05-event-dispatch","事件触发",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":271,"title":272,"meta":273},"\u002Fnotes\u002Freact\u002F08-interview\u002F01-useEffect-vs-useLayoutEffect","useEffect 与 useLayoutEffect 的区别",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":275,"title":276,"meta":277},"\u002Fnotes\u002Freact\u002F08-interview\u002F02-why-no-conditional-hooks","为什么 hook 不能写在条件判断里",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":279,"title":280,"meta":281},"\u002Fnotes\u002Freact\u002F08-interview\u002F03-understanding-concurrency","聊聊在 React 中，你对并发模式的理解",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":283,"title":284,"meta":285},"\u002Fnotes\u002Freact\u002F08-interview\u002F04-update-mechanism","聊聊 React 的更新机制原理",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":287,"title":288,"meta":289},"\u002Fnotes\u002Freact\u002F08-interview\u002F05-setState-sync-or-async","setState 是同步还是异步的？",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":291,"title":292,"meta":293},"\u002Fnotes\u002Freact\u002F08-interview\u002F06-useState-vs-useReducer","聊聊 useState 与 useReducer 的区别",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":295,"title":296,"meta":297},"\u002Fnotes\u002Freact\u002F08-interview\u002F07-closure-trap","聊聊闭包陷阱问题，以及如何解决",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":299,"title":300,"meta":301},"\u002Fnotes\u002Freact\u002F08-interview\u002F08-time-slicing-details","时间分片是如何实现的（任务拆分\u002F中断\u002F恢复）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":303,"title":304,"meta":305},"\u002Fnotes\u002Freact\u002F08-interview\u002F09-batched-updates-useState","聊聊 useState 的批处理更新机制",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":307,"title":308,"meta":309},"\u002Fnotes\u002Freact\u002F08-interview\u002F10-jsx-to-dom","JSX 是如何转变成为真实 DOM 的",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":311,"title":312,"meta":313},"\u002Fnotes\u002Freact\u002F08-interview\u002F11-useCallback-impl","useCallback 的实现原理是什么",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":315,"title":316,"meta":317},"\u002Fnotes\u002Freact\u002F08-interview\u002F12-scheduling-mechanism","详细聊聊 React 的调度机制",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":319,"title":320,"meta":321},"\u002Fnotes\u002Freact\u002F08-interview\u002F13-priority-and-lanes","聊聊 React 的优先级机制（Lane 模型）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":323,"title":324,"meta":325},"\u002Fnotes\u002Freact\u002F08-interview\u002F14-diff-algorithm","React 的 Diff 算法是什么样的",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":327,"title":328,"meta":329},"\u002Fnotes\u002Freact\u002F08-interview\u002F15-event-system","详细聊聊 React 的事件系统是如何实现的",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":331,"title":332,"meta":333},"\u002Fnotes\u002Freact\u002F08-interview\u002F16-portals-bubbling","React Portals 上的事件是否会冒泡到父组件，原理是什么",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":335,"title":336,"meta":337},"\u002Fnotes\u002Freact\u002F08-interview\u002F17-useEffect-impl","useEffect 的实现原理是什么",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":339,"title":340,"meta":341},"\u002Fnotes\u002Freact\u002F08-interview\u002F18-useContext-impl","请聊聊 useContext 的实现原理",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":343,"title":344,"meta":345},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice\u002F01-automatic-batching-and-flushsync","React 18 自动批处理（Automatic Batching）与 flushSync",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":347,"title":348,"meta":349},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice\u002F02-strictmode-and-idempotent-effects","React StrictMode：为什么会“双调用”？（源码\u002F机制视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":351,"title":352,"meta":353},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice\u002F03-transition-useTransition-useDeferredValue","Transition：startTransition \u002F useTransition \u002F useDeferredValue（机制视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":355,"title":356,"meta":357},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice\u002F04-suspense-loading-boundary-design","Suspense：加载态边界如何设计（机制\u002F架构视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":359,"title":360,"meta":361},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice\u002F05-error-boundary-reporting-and-recovery","Error Boundary：兜底、重试与上报（自研 vs Sentry）（机制\u002F架构视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":363,"title":364,"meta":365},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice","React 18 实战（并发特性与默认行为）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":367,"title":368,"meta":369},"\u002Fnotes\u002Freact\u002F10-routing-and-navigation\u002F01-routing-and-url-state-mental-model","路由与 URL State：统一心智模型（架构师视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":371,"title":372,"meta":373},"\u002Fnotes\u002Freact\u002F10-routing-and-navigation\u002F02-tanstack-router-route-tree-search-loader-prefetch","TanStack Router（Vite \u002F SPA）：Route Tree \u002F Search \u002F Loader \u002F Prefetch（落地篇）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":375,"title":376,"meta":377},"\u002Fnotes\u002Freact\u002F10-routing-and-navigation\u002F03-next-app-router-segments-layout-loading-error-not-found-prefetch","Next.js App Router：Segments \u002F Layouts \u002F Loading-Error-NotFound \u002F Prefetch（落地篇）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":379,"title":380,"meta":381},"\u002Fnotes\u002Freact\u002F10-routing-and-navigation","路由与导航（TanStack Router \u002F Next App Router）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":383,"title":384,"meta":385},"\u002Fnotes\u002Freact\u002F11-data-layer\u002F01-state-layering-ui-server-url-global","状态分层：UI \u002F Server \u002F URL \u002F Global（架构师视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":387,"title":388,"meta":389},"\u002Fnotes\u002Freact\u002F11-data-layer\u002F02-tanstack-query-caching-and-invalidation","TanStack Query：缓存模型与失效策略（Caching & Invalidation）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":391,"title":392,"meta":393},"\u002Fnotes\u002Freact\u002F11-data-layer\u002F03-optimistic-updates-and-consistency","TanStack Query：乐观更新与一致性（Optimistic Updates & Consistency）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":395,"title":396,"meta":397},"\u002Fnotes\u002Freact\u002F11-data-layer\u002F04-form-architecture-react-hook-form-validation-performance-testability","表单架构：React Hook Form 的受控\u002F非受控、校验、性能与可测试性（架构师视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":399,"title":400,"meta":401},"\u002Fnotes\u002Freact\u002F11-data-layer","数据层（Server State \u002F 表单 \u002F 状态分层）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":403,"title":404,"meta":405},"\u002Fnotes\u002Freact\u002F12-rendering-and-delivery\u002F01-hydration-mismatch","Hydration mismatch（React \u002F Next.js）：成因、检测、排查清单与工程化规避",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":407,"title":408,"meta":409},"\u002Fnotes\u002Freact\u002F12-rendering-and-delivery\u002F01-nextjs-cache-revalidate-consistency-online-not-updating","Next.js 缓存\u002F重验证与一致性：避免「线上怎么不更新」事故（App Router）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":411,"title":412,"meta":413},"\u002Fnotes\u002Freact\u002F12-rendering-and-delivery\u002F02-csr-ssr-ssg-isr-how-to-choose","CSR vs SSR vs SSG vs ISR：怎么选？边界是什么？（体验 + 成本 + 一致性）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":415,"title":416,"meta":417},"\u002Fnotes\u002Freact\u002F12-rendering-and-delivery\u002F04-streaming-ssr-with-suspense","Streaming SSR + Suspense：提升前端感知性能的利器",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":419,"title":420,"meta":421},"\u002Fnotes\u002Freact\u002F12-rendering-and-delivery","渲染与交付（CSR\u002FSSR\u002FStreaming\u002FHydration\u002F缓存）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":423,"title":424,"meta":425},"\u002Fnotes\u002Freact\u002F13-production-readiness\u002F01-observability-logging-metrics-tracing","前端可观测性体系：日志、指标与链路追踪",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":427,"title":428,"meta":429},"\u002Fnotes\u002Freact\u002F13-production-readiness\u002F02-auth-and-web-security","鉴权与 Web 安全：OAuth, JWT, XSS, CSRF, CSP",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":431,"title":432,"meta":433},"\u002Fnotes\u002Freact\u002F13-production-readiness","生产可用性（错误\u002F可观测\u002F鉴权\u002F安全）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":435,"title":436,"meta":437},"\u002Fnotes\u002Freact\u002F14-performance\u002F01-performance-playbook-and-metrics","前端性能定位 Playbook：从指标到归因",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":439,"title":440,"meta":441},"\u002Fnotes\u002Freact\u002F14-performance\u002F02-rendering-optimization-memo-context-virtualization","React 渲染性能优化：Memo, Context, 与虚拟化",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":443,"title":444,"meta":445},"\u002Fnotes\u002Freact\u002F14-performance\u002F03-asset-and-bundle-optimization","资源与 Bundle 优化：代码分割、图片与 CDN",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":447,"title":448,"meta":449},"\u002Fnotes\u002Freact\u002F14-performance","性能体系（定位 → 优化 → 度量）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":451,"title":452,"meta":453},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture\u002F01-component-system-and-design-system","组件体系与设计系统：构建规模化前端的基石",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":455,"title":456,"meta":457},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture\u002F02-testing-strategy-rtl-e2e-testability","前端测试体系：RTL, E2E 与可测性设计",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":459,"title":460,"meta":461},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture\u002F03-monorepo-and-dependency-management","Monorepo 与依赖治理：pnpm 和 Turborepo",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":463,"title":464,"meta":465},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture\u002F04-cicd-and-quality-gates","CI\u002FCD 与质量门禁：构建可靠的自动化流程",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":467,"title":468,"meta":469},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture\u002F05-bff-and-api-design","BFF 与 API 设计：前端架构师的视角",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":471,"title":472,"meta":473},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture","工程与架构治理（规模化）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":475,"title":476,"meta":477},"\u002Fnotes\u002Freact\u002F16-advanced\u002F01-rsc-and-server-actions-deep-dive","RSC\u002FServer Actions 深水区：边界、约束与缓存一致性",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":479,"title":480,"meta":481},"\u002Fnotes\u002Freact\u002F16-advanced\u002F02-micro-frontend-governance","微前端治理：样式、路由与通信",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":483,"title":484,"meta":485},"\u002Fnotes\u002Freact\u002F16-advanced\u002F03-realtime-and-offline","实时与离线：WebSocket, PWA 与 Service Worker",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":487,"title":488,"meta":489},"\u002Fnotes\u002Freact\u002F16-advanced\u002F04-a11y-i18n-compliance","a11y, i18n 与合规：构建负责任的全球化应用",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":491,"title":492,"meta":493},"\u002Fnotes\u002Freact\u002F16-advanced","进阶专题（按业务需要选做）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"id":495,"type":496,"sourcePath":497,"routePath":403,"path":403,"title":404,"updatedAt":21,"meta":498,"body":500,"toc":3049},"bm90ZTpub3Rlcy9yZWFjdC8xMi1yZW5kZXJpbmctYW5kLWRlbGl2ZXJ5LzAxLWh5ZHJhdGlvbi1taXNtYXRjaC5tZA","note","notes\u002Freact\u002F12-rendering-and-delivery\u002F01-hydration-mismatch.md",{"id":495,"type":496,"sourcePath":497,"slug":499,"title":404,"updatedAt":21,"lastUpdated":21},"react\u002F12-rendering-and-delivery\u002F01-hydration-mismatch",{"type":501,"children":502},"root",[503,511,553,560,565,597,607,625,631,638,680,702,708,726,732,737,743,748,812,822,828,832,910,915,942,957,963,981,987,1027,1033,1041,1049,1055,1123,1129,1137,1143,1203,1209,1248,1254,1345,1351,1398,1404,1442,1448,1454,1474,1487,1492,1751,1759,1765,1770,2146,2152,2157,2192,2200,2214,2219,2240,2251,2265,2270,2308,2312,2325,2331,2337,2347,2480,2498,2504,2513,2645,2653,2666,2672,2680,2794,2802,2823,2829,2834,2839,2852,2858,2863,2867,2880,2886,2937,2943,3044],{"type":504,"tag":505,"props":506,"children":508},"element","h1",{"id":507},"hydration-mismatchreact-nextjs成因检测排查清单与工程化规避",[509],{"type":510,"value":404},"text",{"type":504,"tag":512,"props":513,"children":514},"blockquote",{},[515],{"type":504,"tag":516,"props":517,"children":518},"p",{},[519,521,527,529,542,544,551],{"type":510,"value":520},"一句话结论：",{"type":504,"tag":522,"props":523,"children":524},"strong",{},[525],{"type":510,"value":526},"Hydration mismatch 的本质是「首屏 HTML（server render）与客户端第一次 render 产物不一致」",{"type":510,"value":528},"——React 在 hydration 时无法把事件\u002F状态“贴回”到同一棵 DOM 上，就会告警、丢弃部分 server DOM、甚至整棵树改为客户端重建；修复要点是：",{"type":504,"tag":522,"props":530,"children":531},{},[532,534,540],{"type":510,"value":533},"保证“首屏可见结构 + 关键文本\u002F属性”在 server 与 client 的 ",{"type":504,"tag":535,"props":536,"children":537},"em",{},[538],{"type":510,"value":539},"第一次 render",{"type":510,"value":541}," 完全确定且一致",{"type":510,"value":543},"，把所有“只在浏览器才知道的差异”延后到 ",{"type":504,"tag":545,"props":546,"children":548},"code",{"className":547},[],[549],{"type":510,"value":550},"useEffect",{"type":510,"value":552},"（或明确的 client-only 边界）之后。",{"type":504,"tag":554,"props":555,"children":557},"h2",{"id":556},"_0-这类问题的典型信号symptoms",[558],{"type":510,"value":559},"0. 这类问题的典型信号（Symptoms）",{"type":504,"tag":516,"props":561,"children":562},{},[563],{"type":510,"value":564},"你通常会在控制台\u002FNext overlay 看到类似信息：",{"type":504,"tag":566,"props":567,"children":568},"ul",{},[569,579,588],{"type":504,"tag":570,"props":571,"children":572},"li",{},[573],{"type":504,"tag":545,"props":574,"children":576},{"className":575},[],[577],{"type":510,"value":578},"Warning: Text content did not match. Server: \"...\" Client: \"...\"",{"type":504,"tag":570,"props":580,"children":581},{},[582],{"type":504,"tag":545,"props":583,"children":585},{"className":584},[],[586],{"type":510,"value":587},"Hydration failed because the initial UI does not match what was rendered on the server.",{"type":504,"tag":570,"props":589,"children":590},{},[591],{"type":504,"tag":545,"props":592,"children":594},{"className":593},[],[595],{"type":510,"value":596},"There was an error while hydrating... the entire root will switch to client rendering.",{"type":504,"tag":516,"props":598,"children":599},{},[600,605],{"type":504,"tag":522,"props":601,"children":602},{},[603],{"type":510,"value":604},"用户侧表现",{"type":510,"value":606},"可能是：",{"type":504,"tag":566,"props":608,"children":609},{},[610,615,620],{"type":504,"tag":570,"props":611,"children":612},{},[613],{"type":510,"value":614},"首屏闪一下（server 内容被替换）",{"type":504,"tag":570,"props":616,"children":617},{},[618],{"type":510,"value":619},"点击\u002F输入短暂失灵（事件没正确挂上）",{"type":504,"tag":570,"props":621,"children":622},{},[623],{"type":510,"value":624},"某些组件丢状态（因为 hydration 被迫重建）",{"type":504,"tag":554,"props":626,"children":628},{"id":627},"_1-hydration-到底在做什么机制对齐",[629],{"type":510,"value":630},"1. Hydration 到底在做什么（机制对齐）",{"type":504,"tag":632,"props":633,"children":635},"h3",{"id":634},"_11-ssr-hydration-的两段式",[636],{"type":510,"value":637},"1.1 SSR + Hydration 的两段式",{"type":504,"tag":639,"props":640,"children":641},"ol",{},[642,652],{"type":504,"tag":570,"props":643,"children":644},{},[645,650],{"type":504,"tag":522,"props":646,"children":647},{},[648],{"type":510,"value":649},"Server Render（服务端渲染）",{"type":510,"value":651},"：服务端把 React 组件树渲染成 HTML 字符串（或 streaming chunks），浏览器先拿到可见内容。",{"type":504,"tag":570,"props":653,"children":654},{},[655,660,662],{"type":504,"tag":522,"props":656,"children":657},{},[658],{"type":510,"value":659},"Hydration（客户端水合）",{"type":510,"value":661},"：客户端运行同一棵组件树，React 尝试把“客户端 Fiber 树”与“现有 DOM”对齐，并补上：\n",{"type":504,"tag":566,"props":663,"children":664},{},[665,670,675],{"type":504,"tag":570,"props":666,"children":667},{},[668],{"type":510,"value":669},"事件监听",{"type":504,"tag":570,"props":671,"children":672},{},[673],{"type":510,"value":674},"组件状态（初始 state）",{"type":504,"tag":570,"props":676,"children":677},{},[678],{"type":510,"value":679},"refs 等",{"type":504,"tag":512,"props":681,"children":682},{},[683],{"type":504,"tag":516,"props":684,"children":685},{},[686,688,693,695,700],{"type":510,"value":687},"关键点：Hydration 不是“把 HTML 变成 React”，而是“用 ",{"type":504,"tag":535,"props":689,"children":690},{},[691],{"type":510,"value":692},"客户端第一次 render 的结果",{"type":510,"value":694}," 去匹配现有 DOM”。",{"type":504,"tag":522,"props":696,"children":697},{},[698],{"type":510,"value":699},"只要第一次 render 不一致，就会 mismatch",{"type":510,"value":701},"。",{"type":504,"tag":632,"props":703,"children":705},{"id":704},"_12-nextjs-里的现实情况",[706],{"type":510,"value":707},"1.2 Next.js 里的现实情况",{"type":504,"tag":566,"props":709,"children":710},{},[711,721],{"type":504,"tag":570,"props":712,"children":713},{},[714,719],{"type":504,"tag":522,"props":715,"children":716},{},[717],{"type":510,"value":718},"Client Components 也会在服务端输出 HTML",{"type":510,"value":720},"（用于首屏可见内容），随后在浏览器 hydration。",{"type":504,"tag":570,"props":722,"children":723},{},[724],{"type":510,"value":725},"App Router + RSC\u002FStreaming 下：server 输出可能是分片��，但“每个 chunk 对应的客户端首次 render 结果”仍必须匹配。",{"type":504,"tag":554,"props":727,"children":729},{"id":728},"_2-成因causes从确定性角度分类",[730],{"type":510,"value":731},"2. 成因（Causes）——从“确定性”角度分类",{"type":504,"tag":516,"props":733,"children":734},{},[735],{"type":510,"value":736},"下面按“为什么 server 与 client 会算出不同 UI”来分类（你排查时也按这个顺序扫一遍）。",{"type":504,"tag":632,"props":738,"children":740},{"id":739},"_21-非确定性渲染同一份代码两边算出的值不同",[741],{"type":510,"value":742},"2.1 非确定性渲染（同一份代码，两边算出的值不同）",{"type":504,"tag":516,"props":744,"children":745},{},[746],{"type":510,"value":747},"常见触发器：",{"type":504,"tag":566,"props":749,"children":750},{},[751,770,788,799],{"type":504,"tag":570,"props":752,"children":753},{},[754,760,762,768],{"type":504,"tag":545,"props":755,"children":757},{"className":756},[],[758],{"type":510,"value":759},"Date.now()",{"type":510,"value":761}," \u002F ",{"type":504,"tag":545,"props":763,"children":765},{"className":764},[],[766],{"type":510,"value":767},"new Date()",{"type":510,"value":769},"（时刻不同、时区\u002Flocale 也可能不同）",{"type":504,"tag":570,"props":771,"children":772},{},[773,779,780,786],{"type":504,"tag":545,"props":774,"children":776},{"className":775},[],[777],{"type":510,"value":778},"Math.random()",{"type":510,"value":761},{"type":504,"tag":545,"props":781,"children":783},{"className":782},[],[784],{"type":510,"value":785},"crypto.randomUUID()",{"type":510,"value":787},"（随机数）",{"type":504,"tag":570,"props":789,"children":790},{},[791,797],{"type":504,"tag":545,"props":792,"children":794},{"className":793},[],[795],{"type":510,"value":796},"Intl.*",{"type":510,"value":798}," 格式化（locale\u002Ftimezone、实现差异）",{"type":504,"tag":570,"props":800,"children":801},{},[802,804,810],{"type":510,"value":803},"依赖 ",{"type":504,"tag":545,"props":805,"children":807},{"className":806},[],[808],{"type":510,"value":809},"process.env",{"type":510,"value":811}," \u002F feature flag 在两端取值不同",{"type":504,"tag":516,"props":813,"children":814},{},[815,820],{"type":504,"tag":522,"props":816,"children":817},{},[818],{"type":510,"value":819},"症状",{"type":510,"value":821},"：最常见是“文本不一致”。",{"type":504,"tag":632,"props":823,"children":825},{"id":824},"_22-读取仅客户端可得的信息并影响首次-render",[826],{"type":510,"value":827},"2.2 读取“仅客户端可得”的信息，并影响首次 render",{"type":504,"tag":516,"props":829,"children":830},{},[831],{"type":510,"value":747},{"type":504,"tag":566,"props":833,"children":834},{},[835,865,881,892],{"type":504,"tag":570,"props":836,"children":837},{},[838,844,845,851,852,858,859],{"type":504,"tag":545,"props":839,"children":841},{"className":840},[],[842],{"type":510,"value":843},"window",{"type":510,"value":761},{"type":504,"tag":545,"props":846,"children":848},{"className":847},[],[849],{"type":510,"value":850},"document",{"type":510,"value":761},{"type":504,"tag":545,"props":853,"children":855},{"className":854},[],[856],{"type":510,"value":857},"navigator",{"type":510,"value":761},{"type":504,"tag":545,"props":860,"children":862},{"className":861},[],[863],{"type":510,"value":864},"location",{"type":504,"tag":570,"props":866,"children":867},{},[868,874,875],{"type":504,"tag":545,"props":869,"children":871},{"className":870},[],[872],{"type":510,"value":873},"localStorage",{"type":510,"value":761},{"type":504,"tag":545,"props":876,"children":878},{"className":877},[],[879],{"type":510,"value":880},"sessionStorage",{"type":504,"tag":570,"props":882,"children":883},{},[884,890],{"type":504,"tag":545,"props":885,"children":887},{"className":886},[],[888],{"type":510,"value":889},"matchMedia('(prefers-color-scheme: dark)')",{"type":510,"value":891},"（主题）",{"type":504,"tag":570,"props":893,"children":894},{},[895,901,902,908],{"type":504,"tag":545,"props":896,"children":898},{"className":897},[],[899],{"type":510,"value":900},"window.innerWidth",{"type":510,"value":761},{"type":504,"tag":545,"props":903,"children":905},{"className":904},[],[906],{"type":510,"value":907},"devicePixelRatio",{"type":510,"value":909},"（响应式）",{"type":504,"tag":516,"props":911,"children":912},{},[913],{"type":510,"value":914},"典型写法：",{"type":504,"tag":566,"props":916,"children":917},{},[918,929],{"type":504,"tag":570,"props":919,"children":920},{},[921,923],{"type":510,"value":922},"在 render 里直接读：",{"type":504,"tag":545,"props":924,"children":926},{"className":925},[],[927],{"type":510,"value":928},"const theme = localStorage.getItem('theme')",{"type":504,"tag":570,"props":930,"children":931},{},[932,934,940],{"type":510,"value":933},"通过 ",{"type":504,"tag":545,"props":935,"children":937},{"className":936},[],[938],{"type":510,"value":939},"typeof window !== 'undefined'",{"type":510,"value":941}," 做条件渲染，并改变结构\u002F文本",{"type":504,"tag":512,"props":943,"children":944},{},[945],{"type":504,"tag":516,"props":946,"children":947},{},[948,950,955],{"type":510,"value":949},"注意：",{"type":504,"tag":545,"props":951,"children":953},{"className":952},[],[954],{"type":510,"value":939},{"type":510,"value":956}," 本身不是问题；问题是它导致“首屏结构分叉”。",{"type":504,"tag":632,"props":958,"children":960},{"id":959},"_23-数据不一致server-用了-aclient-首次-render-用了-b",[961],{"type":510,"value":962},"2.3 数据不一致（server 用了 A，client 首次 render 用了 B）",{"type":504,"tag":566,"props":964,"children":965},{},[966,971,976],{"type":504,"tag":570,"props":967,"children":968},{},[969],{"type":510,"value":970},"服务端请求与客户端请求命中不同缓存\u002F不同身份（cookie\u002Fheader）",{"type":504,"tag":570,"props":972,"children":973},{},[974],{"type":510,"value":975},"首屏 HTML 用的是 SSR 数据，但客户端首次 render 直接走“空数据 + loading”，或反之",{"type":504,"tag":570,"props":977,"children":978},{},[979],{"type":510,"value":980},"并发\u002Fstreaming 下 fallback 边界切分不当：server 先吐了 fallback，但 client 首次 render 没有 fallback（或相反）",{"type":504,"tag":632,"props":982,"children":984},{"id":983},"_24-dom-在-hydration-前被外部因素改写",[985],{"type":510,"value":986},"2.4 DOM 在 hydration 前被外部因素改写",{"type":504,"tag":566,"props":988,"children":989},{},[990,995,1000],{"type":504,"tag":570,"props":991,"children":992},{},[993],{"type":510,"value":994},"第三方脚本在 React hydration 前插入\u002F改写节点（广告、埋点、A\u002FB SDK）",{"type":504,"tag":570,"props":996,"children":997},{},[998],{"type":510,"value":999},"浏览器插件改写 DOM",{"type":504,"tag":570,"props":1001,"children":1002},{},[1003,1005,1010,1012,1018,1020,1025],{"type":510,"value":1004},"服务器输出了 ",{"type":504,"tag":522,"props":1006,"children":1007},{},[1008],{"type":510,"value":1009},"无效 HTML 结构",{"type":510,"value":1011},"（例如 ",{"type":504,"tag":545,"props":1013,"children":1015},{"className":1014},[],[1016],{"type":510,"value":1017},"div",{"type":510,"value":1019}," 嵌在 ",{"type":504,"tag":545,"props":1021,"children":1023},{"className":1022},[],[1024],{"type":510,"value":516},{"type":510,"value":1026}," 里），浏览器会“修复 DOM”，导致与 React 预期不同",{"type":504,"tag":632,"props":1028,"children":1030},{"id":1029},"_25-样式类名注入顺序问题css-in-js-style-registry",[1031],{"type":510,"value":1032},"2.5 样式\u002F类名注入顺序问题（CSS-in-JS \u002F style registry）",{"type":504,"tag":566,"props":1034,"children":1035},{},[1036],{"type":504,"tag":570,"props":1037,"children":1038},{},[1039],{"type":510,"value":1040},"典型在 Emotion\u002FStyled-components 等：服务端生成的类名与客户端生成的类名不一致，或注入顺序不同。",{"type":504,"tag":512,"props":1042,"children":1043},{},[1044],{"type":504,"tag":516,"props":1045,"children":1046},{},[1047],{"type":510,"value":1048},"Next App Router 下通常需要对应的“样式 registry”方案，否则很容易遇到 className 不一致。",{"type":504,"tag":554,"props":1050,"children":1052},{"id":1051},"_3-如何检测detection把问题变成可复现",[1053],{"type":510,"value":1054},"3. 如何检测（Detection）——把问题“变成可复现”",{"type":504,"tag":566,"props":1056,"children":1057},{},[1058,1082,1100],{"type":504,"tag":570,"props":1059,"children":1060},{},[1061,1066,1068],{"type":504,"tag":522,"props":1062,"children":1063},{},[1064],{"type":510,"value":1065},"不要只看 dev",{"type":510,"value":1067},"：dev 下包含额外的调试\u002FStrictMode 行为；请尽量用 production build 复现。\n",{"type":504,"tag":566,"props":1069,"children":1070},{},[1071],{"type":504,"tag":570,"props":1072,"children":1073},{},[1074,1076],{"type":510,"value":1075},"Next：",{"type":504,"tag":545,"props":1077,"children":1079},{"className":1078},[],[1080],{"type":510,"value":1081},"next build && next start",{"type":504,"tag":570,"props":1083,"children":1084},{},[1085,1090,1092],{"type":504,"tag":522,"props":1086,"children":1087},{},[1088],{"type":510,"value":1089},"用“View Source”看服务端 HTML",{"type":510,"value":1091},"，用 DevTools Elements 看 hydration 后 DOM。\n",{"type":504,"tag":566,"props":1093,"children":1094},{},[1095],{"type":504,"tag":570,"props":1096,"children":1097},{},[1098],{"type":510,"value":1099},"mismatch 往往体现在：文本、属性（className\u002Faria-*）、节点数量\u002F层级。",{"type":504,"tag":570,"props":1101,"children":1102},{},[1103,1108,1110],{"type":504,"tag":522,"props":1104,"children":1105},{},[1106],{"type":510,"value":1107},"快速二分定位",{"type":510,"value":1109},"：\n",{"type":504,"tag":566,"props":1111,"children":1112},{},[1113,1118],{"type":504,"tag":570,"props":1114,"children":1115},{},[1116],{"type":510,"value":1117},"先把可疑组件替换成静态占位，看告警是否消失",{"type":504,"tag":570,"props":1119,"children":1120},{},[1121],{"type":510,"value":1122},"再逐段恢复，直到复现",{"type":504,"tag":554,"props":1124,"children":1126},{"id":1125},"_4-debugging-checklist排查清单",[1127],{"type":510,"value":1128},"4. Debugging Checklist（排查清单）",{"type":504,"tag":512,"props":1130,"children":1131},{},[1132],{"type":504,"tag":516,"props":1133,"children":1134},{},[1135],{"type":510,"value":1136},"目标：快速判断是「非确定性渲染」还是「数据\u002F外部修改」还是「样式注入」。",{"type":504,"tag":632,"props":1138,"children":1140},{"id":1139},"_41-复现与环境一致性",[1141],{"type":510,"value":1142},"4.1 复现与环境一致性",{"type":504,"tag":566,"props":1144,"children":1147},{"className":1145},[1146],"contains-task-list",[1148,1168,1177,1194],{"type":504,"tag":570,"props":1149,"children":1152},{"className":1150},[1151],"task-list-item",[1153,1159,1161,1166],{"type":504,"tag":1154,"props":1155,"children":1158},"input",{"disabled":1156,"type":1157},true,"checkbox",[],{"type":510,"value":1160}," 是否在 ",{"type":504,"tag":545,"props":1162,"children":1164},{"className":1163},[],[1165],{"type":510,"value":1081},{"type":510,"value":1167}," 下仍能复现？",{"type":504,"tag":570,"props":1169,"children":1171},{"className":1170},[1151],[1172,1175],{"type":504,"tag":1154,"props":1173,"children":1174},{"disabled":1156,"type":1157},[],{"type":510,"value":1176}," 是否在无痕窗口\u002F禁用插件后复现？（排除 DOM 被插件改写）",{"type":504,"tag":570,"props":1178,"children":1180},{"className":1179},[1151],[1181,1184,1186,1192],{"type":504,"tag":1154,"props":1182,"children":1183},{"disabled":1156,"type":1157},[],{"type":510,"value":1185}," 是否只在某些地区\u002F时区\u002F语言环境出现？（",{"type":504,"tag":545,"props":1187,"children":1189},{"className":1188},[],[1190],{"type":510,"value":1191},"Intl",{"type":510,"value":1193},"\u002F时区问题）",{"type":504,"tag":570,"props":1195,"children":1197},{"className":1196},[1151],[1198,1201],{"type":504,"tag":1154,"props":1199,"children":1200},{"disabled":1156,"type":1157},[],{"type":510,"value":1202}," 是否只在登录\u002F特定 cookie 下出现？（身份导致数据分叉）",{"type":504,"tag":632,"props":1204,"children":1206},{"id":1205},"_42-定位-mismatch-的最小子树",[1207],{"type":510,"value":1208},"4.2 定位 mismatch 的“最小子树”",{"type":504,"tag":566,"props":1210,"children":1212},{"className":1211},[1146],[1213,1222,1239],{"type":504,"tag":570,"props":1214,"children":1216},{"className":1215},[1151],[1217,1220],{"type":504,"tag":1154,"props":1218,"children":1219},{"disabled":1156,"type":1157},[],{"type":510,"value":1221}," 控制台\u002Foverlay 是否提示了具体节点（文本 diff）？",{"type":504,"tag":570,"props":1223,"children":1225},{"className":1224},[1151],[1226,1229,1231,1237],{"type":504,"tag":1154,"props":1227,"children":1228},{"disabled":1156,"type":1157},[],{"type":510,"value":1230}," 在可疑区域临时加 ",{"type":504,"tag":545,"props":1232,"children":1234},{"className":1233},[],[1235],{"type":510,"value":1236},"data-debug=\"...\"",{"type":510,"value":1238},"，从 DOM 反查是哪块组件输出的",{"type":504,"tag":570,"props":1240,"children":1242},{"className":1241},[1151],[1243,1246],{"type":504,"tag":1154,"props":1244,"children":1245},{"disabled":1156,"type":1157},[],{"type":510,"value":1247}," 临时把该区域替换为纯静态 HTML，确认告警是否消失（验证定位正确）",{"type":504,"tag":632,"props":1249,"children":1251},{"id":1250},"_43-扫描高频触发器从代码层面",[1252],{"type":510,"value":1253},"4.3 扫描高频触发器（从代码层面）",{"type":504,"tag":566,"props":1255,"children":1257},{"className":1256},[1146],[1258,1286,1302,1319,1336],{"type":504,"tag":570,"props":1259,"children":1261},{"className":1260},[1151],[1262,1265,1267,1272,1273,1278,1279,1284],{"type":504,"tag":1154,"props":1263,"children":1264},{"disabled":1156,"type":1157},[],{"type":510,"value":1266}," 是否在 render\u002F初始化 state 里使用了 ",{"type":504,"tag":545,"props":1268,"children":1270},{"className":1269},[],[1271],{"type":510,"value":759},{"type":510,"value":761},{"type":504,"tag":545,"props":1274,"children":1276},{"className":1275},[],[1277],{"type":510,"value":767},{"type":510,"value":761},{"type":504,"tag":545,"props":1280,"children":1282},{"className":1281},[],[1283],{"type":510,"value":778},{"type":510,"value":1285},"？",{"type":504,"tag":570,"props":1287,"children":1289},{"className":1288},[1151],[1290,1293,1295,1301],{"type":504,"tag":1154,"props":1291,"children":1292},{"disabled":1156,"type":1157},[],{"type":510,"value":1294}," 是否在 render 里读了 ",{"type":504,"tag":545,"props":1296,"children":1298},{"className":1297},[],[1299],{"type":510,"value":1300},"window\u002Fdocument\u002FlocalStorage\u002FmatchMedia",{"type":510,"value":1285},{"type":504,"tag":570,"props":1303,"children":1305},{"className":1304},[1151],[1306,1309,1311,1317],{"type":504,"tag":1154,"props":1307,"children":1308},{"disabled":1156,"type":1157},[],{"type":510,"value":1310}," 是否根据 ",{"type":504,"tag":545,"props":1312,"children":1314},{"className":1313},[],[1315],{"type":510,"value":1316},"typeof window",{"type":510,"value":1318}," 做了结构性分支（多\u002F少节点）？",{"type":504,"tag":570,"props":1320,"children":1322},{"className":1321},[1151],[1323,1326,1328,1334],{"type":504,"tag":1154,"props":1324,"children":1325},{"disabled":1156,"type":1157},[],{"type":510,"value":1327}," 是否有 ",{"type":504,"tag":545,"props":1329,"children":1331},{"className":1330},[],[1332],{"type":510,"value":1333},"dangerouslySetInnerHTML",{"type":510,"value":1335}," 且两端内容来源不同？",{"type":504,"tag":570,"props":1337,"children":1339},{"className":1338},[1151],[1340,1343],{"type":504,"tag":1154,"props":1341,"children":1342},{"disabled":1156,"type":1157},[],{"type":510,"value":1344}," 是否有第三方脚本在 hydration 前执行并改写 DOM？",{"type":504,"tag":632,"props":1346,"children":1348},{"id":1347},"_44-数据一致性next-特有高发区",[1349],{"type":510,"value":1350},"4.4 数据一致性（Next 特有高发区）",{"type":504,"tag":566,"props":1352,"children":1354},{"className":1353},[1146],[1355,1372,1389],{"type":504,"tag":570,"props":1356,"children":1358},{"className":1357},[1151],[1359,1362,1364,1370],{"type":504,"tag":1154,"props":1360,"children":1361},{"disabled":1156,"type":1157},[],{"type":510,"value":1363}," SSR\u002FRSC 用到的 ",{"type":504,"tag":545,"props":1365,"children":1367},{"className":1366},[],[1368],{"type":510,"value":1369},"cookies()\u002Fheaders()",{"type":510,"value":1371}," 是否会让同一路由对不同用户返回不同 HTML？",{"type":504,"tag":570,"props":1373,"children":1375},{"className":1374},[1151],[1376,1379,1381],{"type":504,"tag":1154,"props":1377,"children":1378},{"disabled":1156,"type":1157},[],{"type":510,"value":1380}," 客户端首次 render 是否拿到与服务端相同的“初始数据快照”？\n",{"type":504,"tag":566,"props":1382,"children":1383},{},[1384],{"type":504,"tag":570,"props":1385,"children":1386},{},[1387],{"type":510,"value":1388},"例如：SSR 数据注入、query cache hydrate、RSC payload",{"type":504,"tag":570,"props":1390,"children":1392},{"className":1391},[1151],[1393,1396],{"type":504,"tag":1154,"props":1394,"children":1395},{"disabled":1156,"type":1157},[],{"type":510,"value":1397}," Suspense fallback 是否出现 server\u002Fclient 不一致？（边界切分问题）",{"type":504,"tag":632,"props":1399,"children":1401},{"id":1400},"_45-样式注入与-classname",[1402],{"type":510,"value":1403},"4.5 样式注入与 className",{"type":504,"tag":566,"props":1405,"children":1407},{"className":1406},[1146],[1408,1417],{"type":504,"tag":570,"props":1409,"children":1411},{"className":1410},[1151],[1412,1415],{"type":504,"tag":1154,"props":1413,"children":1414},{"disabled":1156,"type":1157},[],{"type":510,"value":1416}," 是否使用了 CSS-in-JS，但没有做正确的 SSR 提取\u002Fregistry？",{"type":504,"tag":570,"props":1418,"children":1420},{"className":1419},[1151],[1421,1424,1426,1432,1434,1440],{"type":504,"tag":1154,"props":1422,"children":1423},{"disabled":1156,"type":1157},[],{"type":510,"value":1425}," mismatch 是否主要体现在 ",{"type":504,"tag":545,"props":1427,"children":1429},{"className":1428},[],[1430],{"type":510,"value":1431},"class",{"type":510,"value":1433},"\u002F",{"type":504,"tag":545,"props":1435,"children":1437},{"className":1436},[],[1438],{"type":510,"value":1439},"style",{"type":510,"value":1441}," 属性，而非文本\u002F结构？",{"type":504,"tag":554,"props":1443,"children":1445},{"id":1444},"_5-预防与修复模式prevention-patterns",[1446],{"type":510,"value":1447},"5. 预防与修复模式（Prevention Patterns）",{"type":504,"tag":632,"props":1449,"children":1451},{"id":1450},"_51-规则-1首屏-render-必须纯函数-同输入同输出",[1452],{"type":510,"value":1453},"5.1 规则 1：首屏 render 必须“纯函数 + 同输入同输出”",{"type":504,"tag":566,"props":1455,"children":1456},{},[1457,1462],{"type":504,"tag":570,"props":1458,"children":1459},{},[1460],{"type":510,"value":1461},"把随机\u002F时间\u002F浏览器信息都视为“副作用输入”，不要在首屏 render 里读取。",{"type":504,"tag":570,"props":1463,"children":1464},{},[1465,1467,1472],{"type":510,"value":1466},"如果确实要展示，保证 server 与 client ",{"type":504,"tag":522,"props":1468,"children":1469},{},[1470],{"type":510,"value":1471},"用同一份值",{"type":510,"value":1473},"（由 server 计算并下发）。",{"type":504,"tag":632,"props":1475,"children":1477},{"id":1476},"_52-模式-a延后到-useeffectmounted-gate",[1478,1480,1485],{"type":510,"value":1479},"5.2 模式 A：延后到 ",{"type":504,"tag":545,"props":1481,"children":1483},{"className":1482},[],[1484],{"type":510,"value":550},{"type":510,"value":1486},"（mounted gate）",{"type":504,"tag":516,"props":1488,"children":1489},{},[1490],{"type":510,"value":1491},"适用于：主题、窗口尺寸、仅客户端能力检测等。",{"type":504,"tag":1493,"props":1494,"children":1499},"pre",{"className":1495,"code":1496,"language":1497,"meta":1498,"style":1498},"language-tsx shiki shiki-themes github-light github-dark","function ClientOnly({ children }: { children: React.ReactNode }) {\n  const [mounted, setMounted] = React.useState(false);\n  React.useEffect(() => setMounted(true), []);\n  if (!mounted) return null; \u002F\u002F 或返回与 server 相同的占位骨架\n  return children;\n}\n","tsx","",[1500],{"type":504,"tag":545,"props":1501,"children":1502},{"__ignoreMap":1498},[1503,1576,1641,1683,1728,1742],{"type":504,"tag":1504,"props":1505,"children":1508},"span",{"class":1506,"line":1507},"line",1,[1509,1515,1521,1527,1533,1538,1543,1548,1552,1556,1561,1566,1571],{"type":504,"tag":1504,"props":1510,"children":1512},{"style":1511},"--shiki-default:#D73A49;--shiki-dark:#F97583",[1513],{"type":510,"value":1514},"function",{"type":504,"tag":1504,"props":1516,"children":1518},{"style":1517},"--shiki-default:#6F42C1;--shiki-dark:#B392F0",[1519],{"type":510,"value":1520}," ClientOnly",{"type":504,"tag":1504,"props":1522,"children":1524},{"style":1523},"--shiki-default:#24292E;--shiki-dark:#E1E4E8",[1525],{"type":510,"value":1526},"({ ",{"type":504,"tag":1504,"props":1528,"children":1530},{"style":1529},"--shiki-default:#E36209;--shiki-dark:#FFAB70",[1531],{"type":510,"value":1532},"children",{"type":504,"tag":1504,"props":1534,"children":1535},{"style":1523},[1536],{"type":510,"value":1537}," }",{"type":504,"tag":1504,"props":1539,"children":1540},{"style":1511},[1541],{"type":510,"value":1542},":",{"type":504,"tag":1504,"props":1544,"children":1545},{"style":1523},[1546],{"type":510,"value":1547}," { ",{"type":504,"tag":1504,"props":1549,"children":1550},{"style":1529},[1551],{"type":510,"value":1532},{"type":504,"tag":1504,"props":1553,"children":1554},{"style":1511},[1555],{"type":510,"value":1542},{"type":504,"tag":1504,"props":1557,"children":1558},{"style":1517},[1559],{"type":510,"value":1560}," React",{"type":504,"tag":1504,"props":1562,"children":1563},{"style":1523},[1564],{"type":510,"value":1565},".",{"type":504,"tag":1504,"props":1567,"children":1568},{"style":1517},[1569],{"type":510,"value":1570},"ReactNode",{"type":504,"tag":1504,"props":1572,"children":1573},{"style":1523},[1574],{"type":510,"value":1575}," }) {\n",{"type":504,"tag":1504,"props":1577,"children":1579},{"class":1506,"line":1578},2,[1580,1585,1590,1596,1601,1606,1611,1616,1621,1626,1631,1636],{"type":504,"tag":1504,"props":1581,"children":1582},{"style":1511},[1583],{"type":510,"value":1584},"  const",{"type":504,"tag":1504,"props":1586,"children":1587},{"style":1523},[1588],{"type":510,"value":1589}," [",{"type":504,"tag":1504,"props":1591,"children":1593},{"style":1592},"--shiki-default:#005CC5;--shiki-dark:#79B8FF",[1594],{"type":510,"value":1595},"mounted",{"type":504,"tag":1504,"props":1597,"children":1598},{"style":1523},[1599],{"type":510,"value":1600},", ",{"type":504,"tag":1504,"props":1602,"children":1603},{"style":1592},[1604],{"type":510,"value":1605},"setMounted",{"type":504,"tag":1504,"props":1607,"children":1608},{"style":1523},[1609],{"type":510,"value":1610},"] ",{"type":504,"tag":1504,"props":1612,"children":1613},{"style":1511},[1614],{"type":510,"value":1615},"=",{"type":504,"tag":1504,"props":1617,"children":1618},{"style":1523},[1619],{"type":510,"value":1620}," React.",{"type":504,"tag":1504,"props":1622,"children":1623},{"style":1517},[1624],{"type":510,"value":1625},"useState",{"type":504,"tag":1504,"props":1627,"children":1628},{"style":1523},[1629],{"type":510,"value":1630},"(",{"type":504,"tag":1504,"props":1632,"children":1633},{"style":1592},[1634],{"type":510,"value":1635},"false",{"type":504,"tag":1504,"props":1637,"children":1638},{"style":1523},[1639],{"type":510,"value":1640},");\n",{"type":504,"tag":1504,"props":1642,"children":1644},{"class":1506,"line":1643},3,[1645,1650,1654,1659,1664,1669,1673,1678],{"type":504,"tag":1504,"props":1646,"children":1647},{"style":1523},[1648],{"type":510,"value":1649},"  React.",{"type":504,"tag":1504,"props":1651,"children":1652},{"style":1517},[1653],{"type":510,"value":550},{"type":504,"tag":1504,"props":1655,"children":1656},{"style":1523},[1657],{"type":510,"value":1658},"(() ",{"type":504,"tag":1504,"props":1660,"children":1661},{"style":1511},[1662],{"type":510,"value":1663},"=>",{"type":504,"tag":1504,"props":1665,"children":1666},{"style":1517},[1667],{"type":510,"value":1668}," setMounted",{"type":504,"tag":1504,"props":1670,"children":1671},{"style":1523},[1672],{"type":510,"value":1630},{"type":504,"tag":1504,"props":1674,"children":1675},{"style":1592},[1676],{"type":510,"value":1677},"true",{"type":504,"tag":1504,"props":1679,"children":1680},{"style":1523},[1681],{"type":510,"value":1682},"), []);\n",{"type":504,"tag":1504,"props":1684,"children":1686},{"class":1506,"line":1685},4,[1687,1692,1697,1702,1707,1712,1717,1722],{"type":504,"tag":1504,"props":1688,"children":1689},{"style":1511},[1690],{"type":510,"value":1691},"  if",{"type":504,"tag":1504,"props":1693,"children":1694},{"style":1523},[1695],{"type":510,"value":1696}," (",{"type":504,"tag":1504,"props":1698,"children":1699},{"style":1511},[1700],{"type":510,"value":1701},"!",{"type":504,"tag":1504,"props":1703,"children":1704},{"style":1523},[1705],{"type":510,"value":1706},"mounted) ",{"type":504,"tag":1504,"props":1708,"children":1709},{"style":1511},[1710],{"type":510,"value":1711},"return",{"type":504,"tag":1504,"props":1713,"children":1714},{"style":1592},[1715],{"type":510,"value":1716}," null",{"type":504,"tag":1504,"props":1718,"children":1719},{"style":1523},[1720],{"type":510,"value":1721},"; ",{"type":504,"tag":1504,"props":1723,"children":1725},{"style":1724},"--shiki-default:#6A737D;--shiki-dark:#6A737D",[1726],{"type":510,"value":1727},"\u002F\u002F 或返回与 server 相同的占位骨架\n",{"type":504,"tag":1504,"props":1729,"children":1731},{"class":1506,"line":1730},5,[1732,1737],{"type":504,"tag":1504,"props":1733,"children":1734},{"style":1511},[1735],{"type":510,"value":1736},"  return",{"type":504,"tag":1504,"props":1738,"children":1739},{"style":1523},[1740],{"type":510,"value":1741}," children;\n",{"type":504,"tag":1504,"props":1743,"children":1745},{"class":1506,"line":1744},6,[1746],{"type":504,"tag":1504,"props":1747,"children":1748},{"style":1523},[1749],{"type":510,"value":1750},"}\n",{"type":504,"tag":512,"props":1752,"children":1753},{},[1754],{"type":504,"tag":516,"props":1755,"children":1756},{},[1757],{"type":510,"value":1758},"代价：首屏可能少一块内容；如果是关键内容，更推荐“模式 B：同值下发”。",{"type":504,"tag":632,"props":1760,"children":1762},{"id":1761},"_53-模式-b把值变成可序列化的初始-propsserver-决定client-复用",[1763],{"type":510,"value":1764},"5.3 模式 B：把值变成“可序列化的初始 props”（server 决定、client 复用）",{"type":504,"tag":516,"props":1766,"children":1767},{},[1768],{"type":510,"value":1769},"适用于：时间戳、地区、A\u002FB 实验桶、用户信息（可公开部分）等。",{"type":504,"tag":1493,"props":1771,"children":1773},{"className":1495,"code":1772,"language":1497,"meta":1498,"style":1498},"\u002F\u002F server 组件里（或 getServerSideProps 等）\nconst now = Date.now();\nreturn \u003CClock initialNow={now} \u002F>;\n\n\u002F\u002F client 组件\nfunction Clock({ initialNow }: { initialNow: number }) {\n  const [now, setNow] = React.useState(initialNow);\n  React.useEffect(() => {\n    const id = setInterval(() => setNow(Date.now()), 1000);\n    return () => clearInterval(id);\n  }, []);\n  return \u003Cspan>{new Date(now).toLocaleTimeString()}\u003C\u002Fspan>;\n}\n",[1774],{"type":504,"tag":545,"props":1775,"children":1776},{"__ignoreMap":1498},[1777,1785,1818,1849,1857,1865,1915,1961,1986,2045,2073,2082,2138],{"type":504,"tag":1504,"props":1778,"children":1779},{"class":1506,"line":1507},[1780],{"type":504,"tag":1504,"props":1781,"children":1782},{"style":1724},[1783],{"type":510,"value":1784},"\u002F\u002F server 组件里（或 getServerSideProps 等）\n",{"type":504,"tag":1504,"props":1786,"children":1787},{"class":1506,"line":1578},[1788,1793,1798,1803,1808,1813],{"type":504,"tag":1504,"props":1789,"children":1790},{"style":1511},[1791],{"type":510,"value":1792},"const",{"type":504,"tag":1504,"props":1794,"children":1795},{"style":1592},[1796],{"type":510,"value":1797}," now",{"type":504,"tag":1504,"props":1799,"children":1800},{"style":1511},[1801],{"type":510,"value":1802}," =",{"type":504,"tag":1504,"props":1804,"children":1805},{"style":1523},[1806],{"type":510,"value":1807}," Date.",{"type":504,"tag":1504,"props":1809,"children":1810},{"style":1517},[1811],{"type":510,"value":1812},"now",{"type":504,"tag":1504,"props":1814,"children":1815},{"style":1523},[1816],{"type":510,"value":1817},"();\n",{"type":504,"tag":1504,"props":1819,"children":1820},{"class":1506,"line":1643},[1821,1825,1830,1835,1840,1844],{"type":504,"tag":1504,"props":1822,"children":1823},{"style":1511},[1824],{"type":510,"value":1711},{"type":504,"tag":1504,"props":1826,"children":1827},{"style":1523},[1828],{"type":510,"value":1829}," \u003C",{"type":504,"tag":1504,"props":1831,"children":1832},{"style":1592},[1833],{"type":510,"value":1834},"Clock",{"type":504,"tag":1504,"props":1836,"children":1837},{"style":1517},[1838],{"type":510,"value":1839}," initialNow",{"type":504,"tag":1504,"props":1841,"children":1842},{"style":1511},[1843],{"type":510,"value":1615},{"type":504,"tag":1504,"props":1845,"children":1846},{"style":1523},[1847],{"type":510,"value":1848},"{now} \u002F>;\n",{"type":504,"tag":1504,"props":1850,"children":1851},{"class":1506,"line":1685},[1852],{"type":504,"tag":1504,"props":1853,"children":1854},{"emptyLinePlaceholder":1156},[1855],{"type":510,"value":1856},"\n",{"type":504,"tag":1504,"props":1858,"children":1859},{"class":1506,"line":1730},[1860],{"type":504,"tag":1504,"props":1861,"children":1862},{"style":1724},[1863],{"type":510,"value":1864},"\u002F\u002F client 组件\n",{"type":504,"tag":1504,"props":1866,"children":1867},{"class":1506,"line":1744},[1868,1872,1877,1881,1886,1890,1894,1898,1902,1906,1911],{"type":504,"tag":1504,"props":1869,"children":1870},{"style":1511},[1871],{"type":510,"value":1514},{"type":504,"tag":1504,"props":1873,"children":1874},{"style":1517},[1875],{"type":510,"value":1876}," Clock",{"type":504,"tag":1504,"props":1878,"children":1879},{"style":1523},[1880],{"type":510,"value":1526},{"type":504,"tag":1504,"props":1882,"children":1883},{"style":1529},[1884],{"type":510,"value":1885},"initialNow",{"type":504,"tag":1504,"props":1887,"children":1888},{"style":1523},[1889],{"type":510,"value":1537},{"type":504,"tag":1504,"props":1891,"children":1892},{"style":1511},[1893],{"type":510,"value":1542},{"type":504,"tag":1504,"props":1895,"children":1896},{"style":1523},[1897],{"type":510,"value":1547},{"type":504,"tag":1504,"props":1899,"children":1900},{"style":1529},[1901],{"type":510,"value":1885},{"type":504,"tag":1504,"props":1903,"children":1904},{"style":1511},[1905],{"type":510,"value":1542},{"type":504,"tag":1504,"props":1907,"children":1908},{"style":1592},[1909],{"type":510,"value":1910}," number",{"type":504,"tag":1504,"props":1912,"children":1913},{"style":1523},[1914],{"type":510,"value":1575},{"type":504,"tag":1504,"props":1916,"children":1918},{"class":1506,"line":1917},7,[1919,1923,1927,1931,1935,1940,1944,1948,1952,1956],{"type":504,"tag":1504,"props":1920,"children":1921},{"style":1511},[1922],{"type":510,"value":1584},{"type":504,"tag":1504,"props":1924,"children":1925},{"style":1523},[1926],{"type":510,"value":1589},{"type":504,"tag":1504,"props":1928,"children":1929},{"style":1592},[1930],{"type":510,"value":1812},{"type":504,"tag":1504,"props":1932,"children":1933},{"style":1523},[1934],{"type":510,"value":1600},{"type":504,"tag":1504,"props":1936,"children":1937},{"style":1592},[1938],{"type":510,"value":1939},"setNow",{"type":504,"tag":1504,"props":1941,"children":1942},{"style":1523},[1943],{"type":510,"value":1610},{"type":504,"tag":1504,"props":1945,"children":1946},{"style":1511},[1947],{"type":510,"value":1615},{"type":504,"tag":1504,"props":1949,"children":1950},{"style":1523},[1951],{"type":510,"value":1620},{"type":504,"tag":1504,"props":1953,"children":1954},{"style":1517},[1955],{"type":510,"value":1625},{"type":504,"tag":1504,"props":1957,"children":1958},{"style":1523},[1959],{"type":510,"value":1960},"(initialNow);\n",{"type":504,"tag":1504,"props":1962,"children":1964},{"class":1506,"line":1963},8,[1965,1969,1973,1977,1981],{"type":504,"tag":1504,"props":1966,"children":1967},{"style":1523},[1968],{"type":510,"value":1649},{"type":504,"tag":1504,"props":1970,"children":1971},{"style":1517},[1972],{"type":510,"value":550},{"type":504,"tag":1504,"props":1974,"children":1975},{"style":1523},[1976],{"type":510,"value":1658},{"type":504,"tag":1504,"props":1978,"children":1979},{"style":1511},[1980],{"type":510,"value":1663},{"type":504,"tag":1504,"props":1982,"children":1983},{"style":1523},[1984],{"type":510,"value":1985}," {\n",{"type":504,"tag":1504,"props":1987,"children":1989},{"class":1506,"line":1988},9,[1990,1995,2000,2004,2009,2013,2017,2022,2027,2031,2036,2041],{"type":504,"tag":1504,"props":1991,"children":1992},{"style":1511},[1993],{"type":510,"value":1994},"    const",{"type":504,"tag":1504,"props":1996,"children":1997},{"style":1592},[1998],{"type":510,"value":1999}," id",{"type":504,"tag":1504,"props":2001,"children":2002},{"style":1511},[2003],{"type":510,"value":1802},{"type":504,"tag":1504,"props":2005,"children":2006},{"style":1517},[2007],{"type":510,"value":2008}," setInterval",{"type":504,"tag":1504,"props":2010,"children":2011},{"style":1523},[2012],{"type":510,"value":1658},{"type":504,"tag":1504,"props":2014,"children":2015},{"style":1511},[2016],{"type":510,"value":1663},{"type":504,"tag":1504,"props":2018,"children":2019},{"style":1517},[2020],{"type":510,"value":2021}," setNow",{"type":504,"tag":1504,"props":2023,"children":2024},{"style":1523},[2025],{"type":510,"value":2026},"(Date.",{"type":504,"tag":1504,"props":2028,"children":2029},{"style":1517},[2030],{"type":510,"value":1812},{"type":504,"tag":1504,"props":2032,"children":2033},{"style":1523},[2034],{"type":510,"value":2035},"()), ",{"type":504,"tag":1504,"props":2037,"children":2038},{"style":1592},[2039],{"type":510,"value":2040},"1000",{"type":504,"tag":1504,"props":2042,"children":2043},{"style":1523},[2044],{"type":510,"value":1640},{"type":504,"tag":1504,"props":2046,"children":2048},{"class":1506,"line":2047},10,[2049,2054,2059,2063,2068],{"type":504,"tag":1504,"props":2050,"children":2051},{"style":1511},[2052],{"type":510,"value":2053},"    return",{"type":504,"tag":1504,"props":2055,"children":2056},{"style":1523},[2057],{"type":510,"value":2058}," () ",{"type":504,"tag":1504,"props":2060,"children":2061},{"style":1511},[2062],{"type":510,"value":1663},{"type":504,"tag":1504,"props":2064,"children":2065},{"style":1517},[2066],{"type":510,"value":2067}," clearInterval",{"type":504,"tag":1504,"props":2069,"children":2070},{"style":1523},[2071],{"type":510,"value":2072},"(id);\n",{"type":504,"tag":1504,"props":2074,"children":2076},{"class":1506,"line":2075},11,[2077],{"type":504,"tag":1504,"props":2078,"children":2079},{"style":1523},[2080],{"type":510,"value":2081},"  }, []);\n",{"type":504,"tag":1504,"props":2083,"children":2085},{"class":1506,"line":2084},12,[2086,2090,2094,2099,2104,2109,2114,2119,2124,2129,2133],{"type":504,"tag":1504,"props":2087,"children":2088},{"style":1511},[2089],{"type":510,"value":1736},{"type":504,"tag":1504,"props":2091,"children":2092},{"style":1523},[2093],{"type":510,"value":1829},{"type":504,"tag":1504,"props":2095,"children":2097},{"style":2096},"--shiki-default:#22863A;--shiki-dark:#85E89D",[2098],{"type":510,"value":1504},{"type":504,"tag":1504,"props":2100,"children":2101},{"style":1523},[2102],{"type":510,"value":2103},">{",{"type":504,"tag":1504,"props":2105,"children":2106},{"style":1511},[2107],{"type":510,"value":2108},"new",{"type":504,"tag":1504,"props":2110,"children":2111},{"style":1517},[2112],{"type":510,"value":2113}," Date",{"type":504,"tag":1504,"props":2115,"children":2116},{"style":1523},[2117],{"type":510,"value":2118},"(now).",{"type":504,"tag":1504,"props":2120,"children":2121},{"style":1517},[2122],{"type":510,"value":2123},"toLocaleTimeString",{"type":504,"tag":1504,"props":2125,"children":2126},{"style":1523},[2127],{"type":510,"value":2128},"()}\u003C\u002F",{"type":504,"tag":1504,"props":2130,"children":2131},{"style":2096},[2132],{"type":510,"value":1504},{"type":504,"tag":1504,"props":2134,"children":2135},{"style":1523},[2136],{"type":510,"value":2137},">;\n",{"type":504,"tag":1504,"props":2139,"children":2141},{"class":1506,"line":2140},13,[2142],{"type":504,"tag":1504,"props":2143,"children":2144},{"style":1523},[2145],{"type":510,"value":1750},{"type":504,"tag":632,"props":2147,"children":2149},{"id":2148},"_54-模式-cclient-only-边界next-dynamic-client-component-拆分",[2150],{"type":510,"value":2151},"5.4 模式 C：client-only 边界（Next dynamic \u002F Client Component 拆分）",{"type":504,"tag":516,"props":2153,"children":2154},{},[2155],{"type":510,"value":2156},"适用于：第三方库依赖 DOM、广告\u002F地图\u002F富文本编辑器等“必然非同构”的组件。",{"type":504,"tag":566,"props":2158,"children":2159},{},[2160,2171],{"type":504,"tag":570,"props":2161,"children":2162},{},[2163,2165],{"type":510,"value":2164},"Pages Router\u002F通用：",{"type":504,"tag":545,"props":2166,"children":2168},{"className":2167},[],[2169],{"type":510,"value":2170},"dynamic(() => import('.\u002FX'), { ssr: false })",{"type":504,"tag":570,"props":2172,"children":2173},{},[2174,2176,2182,2184,2190],{"type":510,"value":2175},"App Router：把该组件放到 ",{"type":504,"tag":545,"props":2177,"children":2179},{"className":2178},[],[2180],{"type":510,"value":2181},"\"use client\"",{"type":510,"value":2183}," 文件中，再用 ",{"type":504,"tag":545,"props":2185,"children":2187},{"className":2186},[],[2188],{"type":510,"value":2189},"next\u002Fdynamic",{"type":510,"value":2191}," 控制是否 SSR。",{"type":504,"tag":512,"props":2193,"children":2194},{},[2195],{"type":504,"tag":516,"props":2196,"children":2197},{},[2198],{"type":510,"value":2199},"代价：失去 SSR 首屏 HTML；但比“hydration 报错 + 重建”更可控。",{"type":504,"tag":632,"props":2201,"children":2203},{"id":2202},"_55-模式-d外部-store-用-usesyncexternalstore-提供-server-snapshot",[2204,2206,2212],{"type":510,"value":2205},"5.5 模式 D：外部 store 用 ",{"type":504,"tag":545,"props":2207,"children":2209},{"className":2208},[],[2210],{"type":510,"value":2211},"useSyncExternalStore",{"type":510,"value":2213}," 提供 server snapshot",{"type":504,"tag":516,"props":2215,"children":2216},{},[2217],{"type":510,"value":2218},"适用于：从全局 store \u002F media query \u002F storage 同步 UI（并且要 SSR）。",{"type":504,"tag":1493,"props":2220,"children":2224},{"className":2221,"code":2222,"language":2223,"meta":1498,"style":1498},"language-ts shiki shiki-themes github-light github-dark","useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n","ts",[2225],{"type":504,"tag":545,"props":2226,"children":2227},{"__ignoreMap":1498},[2228],{"type":504,"tag":1504,"props":2229,"children":2230},{"class":1506,"line":1507},[2231,2235],{"type":504,"tag":1504,"props":2232,"children":2233},{"style":1517},[2234],{"type":510,"value":2211},{"type":504,"tag":1504,"props":2236,"children":2237},{"style":1523},[2238],{"type":510,"value":2239},"(subscribe, getSnapshot, getServerSnapshot)\n",{"type":504,"tag":516,"props":2241,"children":2242},{},[2243,2245,2250],{"type":510,"value":2244},"核心是：",{"type":504,"tag":522,"props":2246,"children":2247},{},[2248],{"type":510,"value":2249},"server 也要能返回一个与首屏一致的 snapshot",{"type":510,"value":701},{"type":504,"tag":632,"props":2252,"children":2254},{"id":2253},"_56-模式-esuppresshydrationwarning只用于可接受不一致的文本",[2255,2257,2263],{"type":510,"value":2256},"5.6 模式 E：",{"type":504,"tag":545,"props":2258,"children":2260},{"className":2259},[],[2261],{"type":510,"value":2262},"suppressHydrationWarning",{"type":510,"value":2264},"（只用于“可接受不一致”的文本）",{"type":504,"tag":516,"props":2266,"children":2267},{},[2268],{"type":510,"value":2269},"适用：时间、随机推荐等“首屏不一致但无交互含义”的小块文本。",{"type":504,"tag":1493,"props":2271,"children":2273},{"className":1495,"code":2272,"language":1497,"meta":1498,"style":1498},"\u003Cspan suppressHydrationWarning>{clientOnlyText}\u003C\u002Fspan>\n",[2274],{"type":504,"tag":545,"props":2275,"children":2276},{"__ignoreMap":1498},[2277],{"type":504,"tag":1504,"props":2278,"children":2279},{"class":1506,"line":1507},[2280,2285,2289,2294,2299,2303],{"type":504,"tag":1504,"props":2281,"children":2282},{"style":1523},[2283],{"type":510,"value":2284},"\u003C",{"type":504,"tag":1504,"props":2286,"children":2287},{"style":2096},[2288],{"type":510,"value":1504},{"type":504,"tag":1504,"props":2290,"children":2291},{"style":1517},[2292],{"type":510,"value":2293}," suppressHydrationWarning",{"type":504,"tag":1504,"props":2295,"children":2296},{"style":1523},[2297],{"type":510,"value":2298},">{clientOnlyText}\u003C\u002F",{"type":504,"tag":1504,"props":2300,"children":2301},{"style":2096},[2302],{"type":510,"value":1504},{"type":504,"tag":1504,"props":2304,"children":2305},{"style":1523},[2306],{"type":510,"value":2307},">\n",{"type":504,"tag":516,"props":2309,"children":2310},{},[2311],{"type":510,"value":949},{"type":504,"tag":566,"props":2313,"children":2314},{},[2315,2320],{"type":504,"tag":570,"props":2316,"children":2317},{},[2318],{"type":510,"value":2319},"不要把它当成“修复”——它只是“消音”。",{"type":504,"tag":570,"props":2321,"children":2322},{},[2323],{"type":510,"value":2324},"不要对大块结构使用，否则隐藏真正问题。",{"type":504,"tag":554,"props":2326,"children":2328},{"id":2327},"_6-典型场景example-scenarios",[2329],{"type":510,"value":2330},"6. 典型场景（Example Scenarios）",{"type":504,"tag":632,"props":2332,"children":2334},{"id":2333},"_61-根据时间展示问候语serverclient-时区不同",[2335],{"type":510,"value":2336},"6.1 根据时间展示问候语（server\u002Fclient 时区不同）",{"type":504,"tag":516,"props":2338,"children":2339},{},[2340,2345],{"type":504,"tag":522,"props":2341,"children":2342},{},[2343],{"type":510,"value":2344},"坏例子",{"type":510,"value":2346},"（首屏 render 读时间）：",{"type":504,"tag":1493,"props":2348,"children":2350},{"className":1495,"code":2349,"language":1497,"meta":1498,"style":1498},"function Greeting() {\n  const hour = new Date().getHours();\n  return \u003Ch1>{hour \u003C 12 ? 'Good morning' : 'Good afternoon'}\u003C\u002Fh1>;\n}\n",[2351],{"type":504,"tag":545,"props":2352,"children":2353},{"__ignoreMap":1498},[2354,2371,2410,2473],{"type":504,"tag":1504,"props":2355,"children":2356},{"class":1506,"line":1507},[2357,2361,2366],{"type":504,"tag":1504,"props":2358,"children":2359},{"style":1511},[2360],{"type":510,"value":1514},{"type":504,"tag":1504,"props":2362,"children":2363},{"style":1517},[2364],{"type":510,"value":2365}," Greeting",{"type":504,"tag":1504,"props":2367,"children":2368},{"style":1523},[2369],{"type":510,"value":2370},"() {\n",{"type":504,"tag":1504,"props":2372,"children":2373},{"class":1506,"line":1578},[2374,2378,2383,2387,2392,2396,2401,2406],{"type":504,"tag":1504,"props":2375,"children":2376},{"style":1511},[2377],{"type":510,"value":1584},{"type":504,"tag":1504,"props":2379,"children":2380},{"style":1592},[2381],{"type":510,"value":2382}," hour",{"type":504,"tag":1504,"props":2384,"children":2385},{"style":1511},[2386],{"type":510,"value":1802},{"type":504,"tag":1504,"props":2388,"children":2389},{"style":1511},[2390],{"type":510,"value":2391}," new",{"type":504,"tag":1504,"props":2393,"children":2394},{"style":1517},[2395],{"type":510,"value":2113},{"type":504,"tag":1504,"props":2397,"children":2398},{"style":1523},[2399],{"type":510,"value":2400},"().",{"type":504,"tag":1504,"props":2402,"children":2403},{"style":1517},[2404],{"type":510,"value":2405},"getHours",{"type":504,"tag":1504,"props":2407,"children":2408},{"style":1523},[2409],{"type":510,"value":1817},{"type":504,"tag":1504,"props":2411,"children":2412},{"class":1506,"line":1643},[2413,2417,2421,2425,2430,2434,2439,2444,2450,2455,2460,2465,2469],{"type":504,"tag":1504,"props":2414,"children":2415},{"style":1511},[2416],{"type":510,"value":1736},{"type":504,"tag":1504,"props":2418,"children":2419},{"style":1523},[2420],{"type":510,"value":1829},{"type":504,"tag":1504,"props":2422,"children":2423},{"style":2096},[2424],{"type":510,"value":505},{"type":504,"tag":1504,"props":2426,"children":2427},{"style":1523},[2428],{"type":510,"value":2429},">{hour ",{"type":504,"tag":1504,"props":2431,"children":2432},{"style":1511},[2433],{"type":510,"value":2284},{"type":504,"tag":1504,"props":2435,"children":2436},{"style":1592},[2437],{"type":510,"value":2438}," 12",{"type":504,"tag":1504,"props":2440,"children":2441},{"style":1511},[2442],{"type":510,"value":2443}," ?",{"type":504,"tag":1504,"props":2445,"children":2447},{"style":2446},"--shiki-default:#032F62;--shiki-dark:#9ECBFF",[2448],{"type":510,"value":2449}," 'Good morning'",{"type":504,"tag":1504,"props":2451,"children":2452},{"style":1511},[2453],{"type":510,"value":2454}," :",{"type":504,"tag":1504,"props":2456,"children":2457},{"style":2446},[2458],{"type":510,"value":2459}," 'Good afternoon'",{"type":504,"tag":1504,"props":2461,"children":2462},{"style":1523},[2463],{"type":510,"value":2464},"}\u003C\u002F",{"type":504,"tag":1504,"props":2466,"children":2467},{"style":2096},[2468],{"type":510,"value":505},{"type":504,"tag":1504,"props":2470,"children":2471},{"style":1523},[2472],{"type":510,"value":2137},{"type":504,"tag":1504,"props":2474,"children":2475},{"class":1506,"line":1685},[2476],{"type":504,"tag":1504,"props":2477,"children":2478},{"style":1523},[2479],{"type":510,"value":1750},{"type":504,"tag":516,"props":2481,"children":2482},{},[2483,2488,2490,2496],{"type":504,"tag":522,"props":2484,"children":2485},{},[2486],{"type":510,"value":2487},"好例子",{"type":510,"value":2489},"：server 计算 ",{"type":504,"tag":545,"props":2491,"children":2493},{"className":2492},[],[2494],{"type":510,"value":2495},"hour",{"type":510,"value":2497}," 并下发，或首屏固定文案、客户端再更新。",{"type":504,"tag":632,"props":2499,"children":2501},{"id":2500},"_62-深色模式localstorage-classname",[2502],{"type":510,"value":2503},"6.2 深色模式（localStorage + className）",{"type":504,"tag":516,"props":2505,"children":2506},{},[2507,2511],{"type":504,"tag":522,"props":2508,"children":2509},{},[2510],{"type":510,"value":2344},{"type":510,"value":2512},"：",{"type":504,"tag":1493,"props":2514,"children":2516},{"className":1495,"code":2515,"language":1497,"meta":1498,"style":1498},"function ThemeIcon() {\n  const theme = localStorage.getItem('theme');\n  return \u003CIcon name={theme === 'dark' ? 'moon' : 'sun'} \u002F>;\n}\n",[2517],{"type":504,"tag":545,"props":2518,"children":2519},{"__ignoreMap":1498},[2520,2536,2575,2638],{"type":504,"tag":1504,"props":2521,"children":2522},{"class":1506,"line":1507},[2523,2527,2532],{"type":504,"tag":1504,"props":2524,"children":2525},{"style":1511},[2526],{"type":510,"value":1514},{"type":504,"tag":1504,"props":2528,"children":2529},{"style":1517},[2530],{"type":510,"value":2531}," ThemeIcon",{"type":504,"tag":1504,"props":2533,"children":2534},{"style":1523},[2535],{"type":510,"value":2370},{"type":504,"tag":1504,"props":2537,"children":2538},{"class":1506,"line":1578},[2539,2543,2548,2552,2557,2562,2566,2571],{"type":504,"tag":1504,"props":2540,"children":2541},{"style":1511},[2542],{"type":510,"value":1584},{"type":504,"tag":1504,"props":2544,"children":2545},{"style":1592},[2546],{"type":510,"value":2547}," theme",{"type":504,"tag":1504,"props":2549,"children":2550},{"style":1511},[2551],{"type":510,"value":1802},{"type":504,"tag":1504,"props":2553,"children":2554},{"style":1523},[2555],{"type":510,"value":2556}," localStorage.",{"type":504,"tag":1504,"props":2558,"children":2559},{"style":1517},[2560],{"type":510,"value":2561},"getItem",{"type":504,"tag":1504,"props":2563,"children":2564},{"style":1523},[2565],{"type":510,"value":1630},{"type":504,"tag":1504,"props":2567,"children":2568},{"style":2446},[2569],{"type":510,"value":2570},"'theme'",{"type":504,"tag":1504,"props":2572,"children":2573},{"style":1523},[2574],{"type":510,"value":1640},{"type":504,"tag":1504,"props":2576,"children":2577},{"class":1506,"line":1643},[2578,2582,2586,2591,2596,2600,2605,2610,2615,2619,2624,2628,2633],{"type":504,"tag":1504,"props":2579,"children":2580},{"style":1511},[2581],{"type":510,"value":1736},{"type":504,"tag":1504,"props":2583,"children":2584},{"style":1523},[2585],{"type":510,"value":1829},{"type":504,"tag":1504,"props":2587,"children":2588},{"style":1592},[2589],{"type":510,"value":2590},"Icon",{"type":504,"tag":1504,"props":2592,"children":2593},{"style":1517},[2594],{"type":510,"value":2595}," name",{"type":504,"tag":1504,"props":2597,"children":2598},{"style":1511},[2599],{"type":510,"value":1615},{"type":504,"tag":1504,"props":2601,"children":2602},{"style":1523},[2603],{"type":510,"value":2604},"{theme ",{"type":504,"tag":1504,"props":2606,"children":2607},{"style":1511},[2608],{"type":510,"value":2609},"===",{"type":504,"tag":1504,"props":2611,"children":2612},{"style":2446},[2613],{"type":510,"value":2614}," 'dark'",{"type":504,"tag":1504,"props":2616,"children":2617},{"style":1511},[2618],{"type":510,"value":2443},{"type":504,"tag":1504,"props":2620,"children":2621},{"style":2446},[2622],{"type":510,"value":2623}," 'moon'",{"type":504,"tag":1504,"props":2625,"children":2626},{"style":1511},[2627],{"type":510,"value":2454},{"type":504,"tag":1504,"props":2629,"children":2630},{"style":2446},[2631],{"type":510,"value":2632}," 'sun'",{"type":504,"tag":1504,"props":2634,"children":2635},{"style":1523},[2636],{"type":510,"value":2637},"} \u002F>;\n",{"type":504,"tag":1504,"props":2639,"children":2640},{"class":1506,"line":1685},[2641],{"type":504,"tag":1504,"props":2642,"children":2643},{"style":1523},[2644],{"type":510,"value":1750},{"type":504,"tag":516,"props":2646,"children":2647},{},[2648,2652],{"type":504,"tag":522,"props":2649,"children":2650},{},[2651],{"type":510,"value":2487},{"type":510,"value":2512},{"type":504,"tag":566,"props":2654,"children":2655},{},[2656,2661],{"type":504,"tag":570,"props":2657,"children":2658},{},[2659],{"type":510,"value":2660},"首屏由 server 通过 cookie 决定主题 class（或注入 beforeInteractive 脚本先设置 class）",{"type":504,"tag":570,"props":2662,"children":2663},{},[2664],{"type":510,"value":2665},"客户端再接管状态",{"type":504,"tag":632,"props":2667,"children":2669},{"id":2668},"_63-响应式按窗口宽度渲染不同结构",[2670],{"type":510,"value":2671},"6.3 响应式：按窗口宽度渲染不同结构",{"type":504,"tag":516,"props":2673,"children":2674},{},[2675,2679],{"type":504,"tag":522,"props":2676,"children":2677},{},[2678],{"type":510,"value":2344},{"type":510,"value":2512},{"type":504,"tag":1493,"props":2681,"children":2683},{"className":1495,"code":2682,"language":1497,"meta":1498,"style":1498},"function Nav() {\n  const isMobile = window.innerWidth \u003C 768;\n  return isMobile ? \u003CMobileNav \u002F> : \u003CDesktopNav \u002F>;\n}\n",[2684],{"type":504,"tag":545,"props":2685,"children":2686},{"__ignoreMap":1498},[2687,2703,2738,2787],{"type":504,"tag":1504,"props":2688,"children":2689},{"class":1506,"line":1507},[2690,2694,2699],{"type":504,"tag":1504,"props":2691,"children":2692},{"style":1511},[2693],{"type":510,"value":1514},{"type":504,"tag":1504,"props":2695,"children":2696},{"style":1517},[2697],{"type":510,"value":2698}," Nav",{"type":504,"tag":1504,"props":2700,"children":2701},{"style":1523},[2702],{"type":510,"value":2370},{"type":504,"tag":1504,"props":2704,"children":2705},{"class":1506,"line":1578},[2706,2710,2715,2719,2724,2728,2733],{"type":504,"tag":1504,"props":2707,"children":2708},{"style":1511},[2709],{"type":510,"value":1584},{"type":504,"tag":1504,"props":2711,"children":2712},{"style":1592},[2713],{"type":510,"value":2714}," isMobile",{"type":504,"tag":1504,"props":2716,"children":2717},{"style":1511},[2718],{"type":510,"value":1802},{"type":504,"tag":1504,"props":2720,"children":2721},{"style":1523},[2722],{"type":510,"value":2723}," window.innerWidth ",{"type":504,"tag":1504,"props":2725,"children":2726},{"style":1511},[2727],{"type":510,"value":2284},{"type":504,"tag":1504,"props":2729,"children":2730},{"style":1592},[2731],{"type":510,"value":2732}," 768",{"type":504,"tag":1504,"props":2734,"children":2735},{"style":1523},[2736],{"type":510,"value":2737},";\n",{"type":504,"tag":1504,"props":2739,"children":2740},{"class":1506,"line":1643},[2741,2745,2750,2755,2759,2764,2769,2773,2777,2782],{"type":504,"tag":1504,"props":2742,"children":2743},{"style":1511},[2744],{"type":510,"value":1736},{"type":504,"tag":1504,"props":2746,"children":2747},{"style":1523},[2748],{"type":510,"value":2749}," isMobile ",{"type":504,"tag":1504,"props":2751,"children":2752},{"style":1511},[2753],{"type":510,"value":2754},"?",{"type":504,"tag":1504,"props":2756,"children":2757},{"style":1523},[2758],{"type":510,"value":1829},{"type":504,"tag":1504,"props":2760,"children":2761},{"style":1592},[2762],{"type":510,"value":2763},"MobileNav",{"type":504,"tag":1504,"props":2765,"children":2766},{"style":1523},[2767],{"type":510,"value":2768}," \u002F> ",{"type":504,"tag":1504,"props":2770,"children":2771},{"style":1511},[2772],{"type":510,"value":1542},{"type":504,"tag":1504,"props":2774,"children":2775},{"style":1523},[2776],{"type":510,"value":1829},{"type":504,"tag":1504,"props":2778,"children":2779},{"style":1592},[2780],{"type":510,"value":2781},"DesktopNav",{"type":504,"tag":1504,"props":2783,"children":2784},{"style":1523},[2785],{"type":510,"value":2786}," \u002F>;\n",{"type":504,"tag":1504,"props":2788,"children":2789},{"class":1506,"line":1685},[2790],{"type":504,"tag":1504,"props":2791,"children":2792},{"style":1523},[2793],{"type":510,"value":1750},{"type":504,"tag":516,"props":2795,"children":2796},{},[2797,2801],{"type":504,"tag":522,"props":2798,"children":2799},{},[2800],{"type":510,"value":2487},{"type":510,"value":2512},{"type":504,"tag":566,"props":2803,"children":2804},{},[2805,2810],{"type":504,"tag":570,"props":2806,"children":2807},{},[2808],{"type":510,"value":2809},"结构尽量一致，靠 CSS media query 控制展示",{"type":504,"tag":570,"props":2811,"children":2812},{},[2813,2815,2821],{"type":510,"value":2814},"或 server 用 UA 推断并把 ",{"type":504,"tag":545,"props":2816,"children":2818},{"className":2817},[],[2819],{"type":510,"value":2820},"isMobile",{"type":510,"value":2822}," 作为初始 props（注意准确率\u002F边界）",{"type":504,"tag":632,"props":2824,"children":2826},{"id":2825},"_64-suspense-fallback-不一致streaming边界切分",[2827],{"type":510,"value":2828},"6.4 Suspense fallback 不一致（Streaming\u002F边界切分）",{"type":504,"tag":516,"props":2830,"children":2831},{},[2832],{"type":510,"value":2833},"现象：server 吐出了 fallback，但客户端首次 render 没有 fallback（或相反）。",{"type":504,"tag":516,"props":2835,"children":2836},{},[2837],{"type":510,"value":2838},"修复方向：",{"type":504,"tag":566,"props":2840,"children":2841},{},[2842,2847],{"type":504,"tag":570,"props":2843,"children":2844},{},[2845],{"type":510,"value":2846},"调整边界层级（更稳定的 shell + 更少的结构性分叉）",{"type":504,"tag":570,"props":2848,"children":2849},{},[2850],{"type":510,"value":2851},"确保“是否 suspend”在首屏两端一致（数据依赖要统一、避免 client 首次 render 直接走另一条数据路径）",{"type":504,"tag":632,"props":2853,"children":2855},{"id":2854},"_65-第三方脚本改写-dom",[2856],{"type":510,"value":2857},"6.5 第三方脚本改写 DOM",{"type":504,"tag":516,"props":2859,"children":2860},{},[2861],{"type":510,"value":2862},"现象：只有线上有、只有某些浏览器有；React 提示 hydration 失败并重建。",{"type":504,"tag":516,"props":2864,"children":2865},{},[2866],{"type":510,"value":2838},{"type":504,"tag":566,"props":2868,"children":2869},{},[2870,2875],{"type":504,"tag":570,"props":2871,"children":2872},{},[2873],{"type":510,"value":2874},"把第三方脚本延后到 hydration 后执行（Next Script 的 strategy）",{"type":504,"tag":570,"props":2876,"children":2877},{},[2878],{"type":510,"value":2879},"给第三方“可控挂载点”，不要让它插入到 React 管理的 DOM 子树内部",{"type":504,"tag":554,"props":2881,"children":2883},{"id":2882},"_7-经验法则快速决策",[2884],{"type":510,"value":2885},"7. 经验法则（快速决策）",{"type":504,"tag":566,"props":2887,"children":2888},{},[2889,2901,2913,2925],{"type":504,"tag":570,"props":2890,"children":2891},{},[2892,2894,2899],{"type":510,"value":2893},"如果 mismatch 来自“不可避免的客户端差异”（地图、编辑器、广告）：用 ",{"type":504,"tag":522,"props":2895,"children":2896},{},[2897],{"type":510,"value":2898},"client-only",{"type":510,"value":2900},"，别硬 SSR。",{"type":504,"tag":570,"props":2902,"children":2903},{},[2904,2906,2911],{"type":510,"value":2905},"如果 mismatch 来自“随机\u002F时间\u002Flocale”：用 ",{"type":504,"tag":522,"props":2907,"children":2908},{},[2909],{"type":510,"value":2910},"server 下发初值",{"type":510,"value":2912},"，不要在首屏 render 读。",{"type":504,"tag":570,"props":2914,"children":2915},{},[2916,2918,2923],{"type":510,"value":2917},"如果 mismatch 来自“主题\u002F响应式”：优先 ",{"type":504,"tag":522,"props":2919,"children":2920},{},[2921],{"type":510,"value":2922},"首屏一致（cookie\u002F脚本先设置）",{"type":510,"value":2924},"，其次才是 mounted gate。",{"type":504,"tag":570,"props":2926,"children":2927},{},[2928,2930,2935],{"type":510,"value":2929},"如果 mismatch 来自“数据缓存真相不一致”：先把 ",{"type":504,"tag":522,"props":2931,"children":2932},{},[2933],{"type":510,"value":2934},"数据边界",{"type":510,"value":2936},"理清（RSC\u002FSSR vs client cache），再谈 UI。",{"type":504,"tag":554,"props":2938,"children":2940},{"id":2939},"关联阅读repo-内",[2941],{"type":510,"value":2942},"关联阅读（repo 内）",{"type":504,"tag":566,"props":2944,"children":2945},{},[2946,2961,2975,2989,3003,3030],{"type":504,"tag":570,"props":2947,"children":2948},{},[2949,2951],{"type":510,"value":2950},"渲染与交付总览：",{"type":504,"tag":2952,"props":2953,"children":2955},"a",{"href":2954},".\u002FREADME.md",[2956],{"type":504,"tag":545,"props":2957,"children":2959},{"className":2958},[],[2960],{"type":510,"value":2954},{"type":504,"tag":570,"props":2962,"children":2963},{},[2964,2966],{"type":510,"value":2965},"Suspense 边界设计（含 hydration mismatch 提醒）：",{"type":504,"tag":2952,"props":2967,"children":2969},{"href":2968},"..\u002F09-react-18-in-practice\u002F04-suspense-loading-boundary-design.md",[2970],{"type":504,"tag":545,"props":2971,"children":2973},{"className":2972},[],[2974],{"type":510,"value":2968},{"type":504,"tag":570,"props":2976,"children":2977},{},[2978,2980],{"type":510,"value":2979},"Next App Router 边界树（loading\u002Ferror\u002Fnot-found）：",{"type":504,"tag":2952,"props":2981,"children":2983},{"href":2982},"..\u002F10-routing-and-navigation\u002F03-next-app-router-segments-layout-loading-error-not-found-prefetch.md",[2984],{"type":504,"tag":545,"props":2985,"children":2987},{"className":2986},[],[2988],{"type":510,"value":2982},{"type":504,"tag":570,"props":2990,"children":2991},{},[2992,2994],{"type":510,"value":2993},"Render vs Commit（理解 hydration 属于“挂载\u002F提交”阶段问题）：",{"type":504,"tag":2952,"props":2995,"children":2997},{"href":2996},"..\u002F01-basics\u002F02-render-vs-commit.md",[2998],{"type":504,"tag":545,"props":2999,"children":3001},{"className":3000},[],[3002],{"type":510,"value":2996},{"type":504,"tag":570,"props":3004,"children":3005},{},[3006,3011,3013,3019,3021],{"type":504,"tag":545,"props":3007,"children":3009},{"className":3008},[],[3010],{"type":510,"value":550},{"type":510,"value":3012}," vs ",{"type":504,"tag":545,"props":3014,"children":3016},{"className":3015},[],[3017],{"type":510,"value":3018},"useLayoutEffect",{"type":510,"value":3020},"（SSR 注意点）：",{"type":504,"tag":2952,"props":3022,"children":3024},{"href":3023},"..\u002F08-interview\u002F01-useEffect-vs-useLayoutEffect.md",[3025],{"type":504,"tag":545,"props":3026,"children":3028},{"className":3027},[],[3029],{"type":510,"value":3023},{"type":504,"tag":570,"props":3031,"children":3032},{},[3033,3035],{"type":510,"value":3034},"StrictMode 与幂等 effect（排查时避免被 dev 行为误导）：",{"type":504,"tag":2952,"props":3036,"children":3038},{"href":3037},"..\u002F09-react-18-in-practice\u002F02-strictmode-and-idempotent-effects.md",[3039],{"type":504,"tag":545,"props":3040,"children":3042},{"className":3041},[],[3043],{"type":510,"value":3037},{"type":504,"tag":1439,"props":3045,"children":3046},{},[3047],{"type":510,"value":3048},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":1498,"searchDepth":1578,"depth":1578,"links":3050},[3051,3052,3056,3063,3064,3071,3082,3089,3090],{"id":556,"depth":1578,"text":559},{"id":627,"depth":1578,"text":630,"children":3053},[3054,3055],{"id":634,"depth":1643,"text":637},{"id":704,"depth":1643,"text":707},{"id":728,"depth":1578,"text":731,"children":3057},[3058,3059,3060,3061,3062],{"id":739,"depth":1643,"text":742},{"id":824,"depth":1643,"text":827},{"id":959,"depth":1643,"text":962},{"id":983,"depth":1643,"text":986},{"id":1029,"depth":1643,"text":1032},{"id":1051,"depth":1578,"text":1054},{"id":1125,"depth":1578,"text":1128,"children":3065},[3066,3067,3068,3069,3070],{"id":1139,"depth":1643,"text":1142},{"id":1205,"depth":1643,"text":1208},{"id":1250,"depth":1643,"text":1253},{"id":1347,"depth":1643,"text":1350},{"id":1400,"depth":1643,"text":1403},{"id":1444,"depth":1578,"text":1447,"children":3072},[3073,3074,3076,3077,3078,3080],{"id":1450,"depth":1643,"text":1453},{"id":1476,"depth":1643,"text":3075},"5.2 模式 A：延后到 useEffect（mounted gate）",{"id":1761,"depth":1643,"text":1764},{"id":2148,"depth":1643,"text":2151},{"id":2202,"depth":1643,"text":3079},"5.5 模式 D：外部 store 用 useSyncExternalStore 提供 server snapshot",{"id":2253,"depth":1643,"text":3081},"5.6 模式 E：suppressHydrationWarning（只用于“可接受不一致”的文本）",{"id":2327,"depth":1578,"text":2330,"children":3083},[3084,3085,3086,3087,3088],{"id":2333,"depth":1643,"text":2336},{"id":2500,"depth":1643,"text":2503},{"id":2668,"depth":1643,"text":2671},{"id":2825,"depth":1643,"text":2828},{"id":2854,"depth":1643,"text":2857},{"id":2882,"depth":1578,"text":2885},{"id":2939,"depth":1578,"text":2942},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":3092},"\u003Cpath fill=\"currentColor\" d=\"m10.828 12l4.95 4.95l-1.414 1.415L8 12l6.364-6.364l1.414 1.414z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":3094},"\u003Cpath fill=\"currentColor\" d=\"M3 4h18v2H3zm0 7h12v2H3zm0 7h18v2H3z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":3096},"\u003Cpath fill=\"currentColor\" d=\"m13.172 12l-4.95-4.95l1.414-1.413L16 12l-6.364 6.364l-1.414-1.415z\"\u002F>",{"left":4,"top":4,"width":3098,"height":3098,"rotate":4,"vFlip":6,"hFlip":6,"body":3099},1024,"\u003Cpath fill=\"currentColor\" d=\"M768 832a128 128 0 0 1-128 128H192A128 128 0 0 1 64 832V384a128 128 0 0 1 128-128v64a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64z\"\u002F>\u003Cpath fill=\"currentColor\" d=\"M384 128a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64V192a64 64 0 0 0-64-64zm0-64h448a128 128 0 0 1 128 128v448a128 128 0 0 1-128 128H384a128 128 0 0 1-128-128V192A128 128 0 0 1 384 64\"\u002F>"]