[{"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-15-engineering-and-architecture\u002F03-monorepo-and-dependency-management":494,"i-ri:arrow-left-s-line":2123,"i-ri:menu-2-line":2125,"i-ri:arrow-right-s-line":2127,"i-ep:copy-document":2129},{"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":459,"path":459,"title":460,"updatedAt":21,"meta":498,"body":500,"toc":2110},"bm90ZTpub3Rlcy9yZWFjdC8xNS1lbmdpbmVlcmluZy1hbmQtYXJjaGl0ZWN0dXJlLzAzLW1vbm9yZXBvLWFuZC1kZXBlbmRlbmN5LW1hbmFnZW1lbnQubWQ","note","notes\u002Freact\u002F15-engineering-and-architecture\u002F03-monorepo-and-dependency-management.md",{"id":495,"type":496,"sourcePath":497,"slug":499,"title":460,"updatedAt":21,"lastUpdated":21},"react\u002F15-engineering-and-architecture\u002F03-monorepo-and-dependency-management",{"type":501,"children":502},"root",[503,511,527,531,538,543,613,616,622,641,648,694,740,746,1228,1231,1237,1249,1255,1347,1352,1923,1942,1945,1951,1956,2042,2045,2051,2104],{"type":504,"tag":505,"props":506,"children":508},"element","h1",{"id":507},"monorepo-与依赖治理pnpm-和-turborepo",[509],{"type":510,"value":460},"text",{"type":504,"tag":512,"props":513,"children":514},"blockquote",{},[515],{"type":504,"tag":516,"props":517,"children":518},"p",{},[519,525],{"type":504,"tag":520,"props":521,"children":522},"strong",{},[523],{"type":510,"value":524},"一句话结论",{"type":510,"value":526},"：采用 pnpm workspaces 管理的 Monorepo，并通过 Turborepo 实现智能、高效的任务编排，是现代大型前端项目解决代码复用、依赖管理和工程效率三大挑战的最佳实践。",{"type":504,"tag":528,"props":529,"children":530},"hr",{},[],{"type":504,"tag":532,"props":533,"children":535},"h2",{"id":534},"_1-为什么要使用-monorepo",[536],{"type":510,"value":537},"1. 为什么要使用 Monorepo？",{"type":504,"tag":516,"props":539,"children":540},{},[541],{"type":510,"value":542},"Monorepo 是一个包含多个独立项目或包（packages）的单一代码仓库。与传统的 Polyrepo（每个项目一个仓库）相比，它具有显著优势：",{"type":504,"tag":544,"props":545,"children":546},"ul",{},[547,583,593,603],{"type":504,"tag":548,"props":549,"children":550},"li",{},[551,556,558,565,567,573,575,581],{"type":504,"tag":520,"props":552,"children":553},{},[554],{"type":510,"value":555},"代码复用与共享",{"type":510,"value":557},"：跨项目共享通用组件（如 ",{"type":504,"tag":559,"props":560,"children":562},"code",{"className":561},[],[563],{"type":510,"value":564},"ui",{"type":510,"value":566},"）、工具函数（如 ",{"type":504,"tag":559,"props":568,"children":570},{"className":569},[],[571],{"type":510,"value":572},"utils",{"type":510,"value":574},"）或配置（如 ",{"type":504,"tag":559,"props":576,"children":578},{"className":577},[],[579],{"type":510,"value":580},"eslint-config-custom",{"type":510,"value":582},"）变得极其简单，无需发布到 npm。",{"type":504,"tag":548,"props":584,"children":585},{},[586,591],{"type":504,"tag":520,"props":587,"children":588},{},[589],{"type":510,"value":590},"原子化提交 (Atomic Commits)",{"type":510,"value":592},"：一次提交可以跨越多个包，轻松完成需要同时修改前端、后端和共享库的复杂功能，保证了代码的一致性。",{"type":504,"tag":548,"props":594,"children":595},{},[596,601],{"type":504,"tag":520,"props":597,"children":598},{},[599],{"type":510,"value":600},"集中化依赖管理",{"type":510,"value":602},"：所有项目共享一个 lockfile，避免了版本冲突，简化了依赖升级。",{"type":504,"tag":548,"props":604,"children":605},{},[606,611],{"type":504,"tag":520,"props":607,"children":608},{},[609],{"type":510,"value":610},"统一的开发体验",{"type":510,"value":612},"：所有项目遵循相同的构建、测试和发布流程，降低了新成员的上手成本。",{"type":504,"tag":528,"props":614,"children":615},{},[],{"type":504,"tag":532,"props":617,"children":619},{"id":618},"_2-依赖管理pnpm-workspaces",[620],{"type":510,"value":621},"2. 依赖管理：pnpm Workspaces",{"type":504,"tag":516,"props":623,"children":624},{},[625,631,633,639],{"type":504,"tag":559,"props":626,"children":628},{"className":627},[],[629],{"type":510,"value":630},"pnpm",{"type":510,"value":632}," 是一个快速、磁盘空间高效的包管理器。它的 ",{"type":504,"tag":559,"props":634,"children":636},{"className":635},[],[637],{"type":510,"value":638},"workspaces",{"type":510,"value":640}," 功能是实现 Monorepo 的基石。",{"type":504,"tag":642,"props":643,"children":645},"h3",{"id":644},"a-核心原理",[646],{"type":510,"value":647},"A. 核心原理",{"type":504,"tag":516,"props":649,"children":650},{},[651,656,658,663,665,671,673,678,680,685,687,692],{"type":504,"tag":559,"props":652,"children":654},{"className":653},[],[655],{"type":510,"value":630},{"type":510,"value":657}," 使用一种创新的",{"type":504,"tag":520,"props":659,"children":660},{},[661],{"type":510,"value":662},"内容寻址存储",{"type":510,"value":664},"来管理 ",{"type":504,"tag":559,"props":666,"children":668},{"className":667},[],[669],{"type":510,"value":670},"node_modules",{"type":510,"value":672},"。所有依赖项都被存储在一个全局的、集中的 store 中，然后在每个项目中通过",{"type":504,"tag":520,"props":674,"children":675},{},[676],{"type":510,"value":677},"硬链接 (hard links)",{"type":510,"value":679}," 和",{"type":504,"tag":520,"props":681,"children":682},{},[683],{"type":510,"value":684},"符号链接 (symlinks)",{"type":510,"value":686}," 组合出 ",{"type":504,"tag":559,"props":688,"children":690},{"className":689},[],[691],{"type":510,"value":670},{"type":510,"value":693}," 目录。",{"type":504,"tag":544,"props":695,"children":696},{},[697,707,717],{"type":504,"tag":548,"props":698,"children":699},{},[700,705],{"type":504,"tag":520,"props":701,"children":702},{},[703],{"type":510,"value":704},"磁盘高效",{"type":510,"value":706},"：同一个包的同一个版本在磁盘上只存储一份。",{"type":504,"tag":548,"props":708,"children":709},{},[710,715],{"type":504,"tag":520,"props":711,"children":712},{},[713],{"type":510,"value":714},"安装速度快",{"type":510,"value":716},"：如果依赖已存在于 store 中，安装过程几乎是瞬时的。",{"type":504,"tag":548,"props":718,"children":719},{},[720,730,732,738],{"type":504,"tag":520,"props":721,"children":722},{},[723,725],{"type":510,"value":724},"非扁平化 ",{"type":504,"tag":559,"props":726,"children":728},{"className":727},[],[729],{"type":510,"value":670},{"type":510,"value":731},"：解决了“幻影依赖”问题。你的代码只能访问到在 ",{"type":504,"tag":559,"props":733,"children":735},{"className":734},[],[736],{"type":510,"value":737},"package.json",{"type":510,"value":739}," 中明确声明的依赖。",{"type":504,"tag":642,"props":741,"children":743},{"id":742},"b-如何设置",[744],{"type":510,"value":745},"B. 如何设置",{"type":504,"tag":747,"props":748,"children":749},"ol",{},[750,772,841,1054],{"type":504,"tag":548,"props":751,"children":752},{},[753,758,760],{"type":504,"tag":520,"props":754,"children":755},{},[756],{"type":510,"value":757},"项目结构",{"type":510,"value":759},"：",{"type":504,"tag":761,"props":762,"children":766},"pre",{"className":763,"code":765,"language":510},[764],"language-text","\u002F\n├── apps\u002F\n│   ├── web\u002F (一个 Next.js 应用)\n│   └── docs\u002F (一个文档网站)\n├── packages\u002F\n│   ├── ui\u002F (共享 React 组件库)\n│   ├── utils\u002F (共享工具函数)\n│   └── eslint-config-custom\u002F\n├── package.json\n└── pnpm-workspace.yaml\n",[767],{"type":504,"tag":559,"props":768,"children":770},{"__ignoreMap":769},"",[771],{"type":510,"value":765},{"type":504,"tag":548,"props":773,"children":774},{},[775,784,786],{"type":504,"tag":520,"props":776,"children":777},{},[778],{"type":504,"tag":559,"props":779,"children":781},{"className":780},[],[782],{"type":510,"value":783},"pnpm-workspace.yaml",{"type":510,"value":785},"：在仓库根目录创建此文件，定义工作区的范围。",{"type":504,"tag":761,"props":787,"children":791},{"className":788,"code":789,"language":790,"meta":769,"style":769},"language-yaml shiki shiki-themes github-light github-dark","packages:\n  - 'apps\u002F*'\n  - 'packages\u002F*'\n","yaml",[792],{"type":504,"tag":559,"props":793,"children":794},{"__ignoreMap":769},[795,813,828],{"type":504,"tag":796,"props":797,"children":800},"span",{"class":798,"line":799},"line",1,[801,807],{"type":504,"tag":796,"props":802,"children":804},{"style":803},"--shiki-default:#22863A;--shiki-dark:#85E89D",[805],{"type":510,"value":806},"packages",{"type":504,"tag":796,"props":808,"children":810},{"style":809},"--shiki-default:#24292E;--shiki-dark:#E1E4E8",[811],{"type":510,"value":812},":\n",{"type":504,"tag":796,"props":814,"children":816},{"class":798,"line":815},2,[817,822],{"type":504,"tag":796,"props":818,"children":819},{"style":809},[820],{"type":510,"value":821},"  - ",{"type":504,"tag":796,"props":823,"children":825},{"style":824},"--shiki-default:#032F62;--shiki-dark:#9ECBFF",[826],{"type":510,"value":827},"'apps\u002F*'\n",{"type":504,"tag":796,"props":829,"children":831},{"class":798,"line":830},3,[832,836],{"type":504,"tag":796,"props":833,"children":834},{"style":809},[835],{"type":510,"value":821},{"type":504,"tag":796,"props":837,"children":838},{"style":824},[839],{"type":510,"value":840},"'packages\u002F*'\n",{"type":504,"tag":548,"props":842,"children":843},{},[844,854,855],{"type":504,"tag":520,"props":845,"children":846},{},[847,849],{"type":510,"value":848},"根 ",{"type":504,"tag":559,"props":850,"children":852},{"className":851},[],[853],{"type":510,"value":737},{"type":510,"value":759},{"type":504,"tag":761,"props":856,"children":860},{"className":857,"code":858,"language":859,"meta":769,"style":769},"language-json shiki shiki-themes github-light github-dark","{\n  \"name\": \"my-monorepo\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"pnpm --filter web dev\", \u002F\u002F 仅运行 web 应用的 dev 脚本\n    \"build\": \"pnpm -r build\" \u002F\u002F 在所有包中运行 build 脚本\n  },\n  \"devDependencies\": {\n    \"typescript\": \"latest\",\n    \u002F\u002F ... 其他共享的开发依赖\n  }\n}\n","json",[861],{"type":504,"tag":559,"props":862,"children":863},{"__ignoreMap":769},[864,872,896,917,931,960,983,992,1005,1027,1036,1045],{"type":504,"tag":796,"props":865,"children":866},{"class":798,"line":799},[867],{"type":504,"tag":796,"props":868,"children":869},{"style":809},[870],{"type":510,"value":871},"{\n",{"type":504,"tag":796,"props":873,"children":874},{"class":798,"line":815},[875,881,886,891],{"type":504,"tag":796,"props":876,"children":878},{"style":877},"--shiki-default:#005CC5;--shiki-dark:#79B8FF",[879],{"type":510,"value":880},"  \"name\"",{"type":504,"tag":796,"props":882,"children":883},{"style":809},[884],{"type":510,"value":885},": ",{"type":504,"tag":796,"props":887,"children":888},{"style":824},[889],{"type":510,"value":890},"\"my-monorepo\"",{"type":504,"tag":796,"props":892,"children":893},{"style":809},[894],{"type":510,"value":895},",\n",{"type":504,"tag":796,"props":897,"children":898},{"class":798,"line":830},[899,904,908,913],{"type":504,"tag":796,"props":900,"children":901},{"style":877},[902],{"type":510,"value":903},"  \"private\"",{"type":504,"tag":796,"props":905,"children":906},{"style":809},[907],{"type":510,"value":885},{"type":504,"tag":796,"props":909,"children":910},{"style":877},[911],{"type":510,"value":912},"true",{"type":504,"tag":796,"props":914,"children":915},{"style":809},[916],{"type":510,"value":895},{"type":504,"tag":796,"props":918,"children":920},{"class":798,"line":919},4,[921,926],{"type":504,"tag":796,"props":922,"children":923},{"style":877},[924],{"type":510,"value":925},"  \"scripts\"",{"type":504,"tag":796,"props":927,"children":928},{"style":809},[929],{"type":510,"value":930},": {\n",{"type":504,"tag":796,"props":932,"children":934},{"class":798,"line":933},5,[935,940,944,949,954],{"type":504,"tag":796,"props":936,"children":937},{"style":877},[938],{"type":510,"value":939},"    \"dev\"",{"type":504,"tag":796,"props":941,"children":942},{"style":809},[943],{"type":510,"value":885},{"type":504,"tag":796,"props":945,"children":946},{"style":824},[947],{"type":510,"value":948},"\"pnpm --filter web dev\"",{"type":504,"tag":796,"props":950,"children":951},{"style":809},[952],{"type":510,"value":953},", ",{"type":504,"tag":796,"props":955,"children":957},{"style":956},"--shiki-default:#6A737D;--shiki-dark:#6A737D",[958],{"type":510,"value":959},"\u002F\u002F 仅运行 web 应用的 dev 脚本\n",{"type":504,"tag":796,"props":961,"children":963},{"class":798,"line":962},6,[964,969,973,978],{"type":504,"tag":796,"props":965,"children":966},{"style":877},[967],{"type":510,"value":968},"    \"build\"",{"type":504,"tag":796,"props":970,"children":971},{"style":809},[972],{"type":510,"value":885},{"type":504,"tag":796,"props":974,"children":975},{"style":824},[976],{"type":510,"value":977},"\"pnpm -r build\"",{"type":504,"tag":796,"props":979,"children":980},{"style":956},[981],{"type":510,"value":982}," \u002F\u002F 在所有包中运行 build 脚本\n",{"type":504,"tag":796,"props":984,"children":986},{"class":798,"line":985},7,[987],{"type":504,"tag":796,"props":988,"children":989},{"style":809},[990],{"type":510,"value":991},"  },\n",{"type":504,"tag":796,"props":993,"children":995},{"class":798,"line":994},8,[996,1001],{"type":504,"tag":796,"props":997,"children":998},{"style":877},[999],{"type":510,"value":1000},"  \"devDependencies\"",{"type":504,"tag":796,"props":1002,"children":1003},{"style":809},[1004],{"type":510,"value":930},{"type":504,"tag":796,"props":1006,"children":1008},{"class":798,"line":1007},9,[1009,1014,1018,1023],{"type":504,"tag":796,"props":1010,"children":1011},{"style":877},[1012],{"type":510,"value":1013},"    \"typescript\"",{"type":504,"tag":796,"props":1015,"children":1016},{"style":809},[1017],{"type":510,"value":885},{"type":504,"tag":796,"props":1019,"children":1020},{"style":824},[1021],{"type":510,"value":1022},"\"latest\"",{"type":504,"tag":796,"props":1024,"children":1025},{"style":809},[1026],{"type":510,"value":895},{"type":504,"tag":796,"props":1028,"children":1030},{"class":798,"line":1029},10,[1031],{"type":504,"tag":796,"props":1032,"children":1033},{"style":956},[1034],{"type":510,"value":1035},"    \u002F\u002F ... 其他共享的开发依赖\n",{"type":504,"tag":796,"props":1037,"children":1039},{"class":798,"line":1038},11,[1040],{"type":504,"tag":796,"props":1041,"children":1042},{"style":809},[1043],{"type":510,"value":1044},"  }\n",{"type":504,"tag":796,"props":1046,"children":1048},{"class":798,"line":1047},12,[1049],{"type":504,"tag":796,"props":1050,"children":1051},{"style":809},[1052],{"type":510,"value":1053},"}\n",{"type":504,"tag":548,"props":1055,"children":1056},{},[1057,1062,1064,1070,1072,1078,1080,1170,1174,1176,1182,1184,1189,1191,1197,1199,1204,1206,1211,1213,1218,1220,1226],{"type":504,"tag":520,"props":1058,"children":1059},{},[1060],{"type":510,"value":1061},"本地包链接",{"type":510,"value":1063},"：现在，",{"type":504,"tag":559,"props":1065,"children":1067},{"className":1066},[],[1068],{"type":510,"value":1069},"apps\u002Fweb",{"type":510,"value":1071}," 可以像使用 npm 包一样直接引用 ",{"type":504,"tag":559,"props":1073,"children":1075},{"className":1074},[],[1076],{"type":510,"value":1077},"packages\u002Fui",{"type":510,"value":1079},"。",{"type":504,"tag":761,"props":1081,"children":1083},{"className":857,"code":1082,"language":859,"meta":769,"style":769},"\u002F\u002F apps\u002Fweb\u002Fpackage.json\n{\n  \"name\": \"web\",\n  \"dependencies\": {\n    \"ui\": \"workspace:*\" \u002F\u002F \"workspace:*\" 会自动链接到本地的 ui 包\n  }\n}\n",[1084],{"type":504,"tag":559,"props":1085,"children":1086},{"__ignoreMap":769},[1087,1095,1102,1122,1134,1156,1163],{"type":504,"tag":796,"props":1088,"children":1089},{"class":798,"line":799},[1090],{"type":504,"tag":796,"props":1091,"children":1092},{"style":956},[1093],{"type":510,"value":1094},"\u002F\u002F apps\u002Fweb\u002Fpackage.json\n",{"type":504,"tag":796,"props":1096,"children":1097},{"class":798,"line":815},[1098],{"type":504,"tag":796,"props":1099,"children":1100},{"style":809},[1101],{"type":510,"value":871},{"type":504,"tag":796,"props":1103,"children":1104},{"class":798,"line":830},[1105,1109,1113,1118],{"type":504,"tag":796,"props":1106,"children":1107},{"style":877},[1108],{"type":510,"value":880},{"type":504,"tag":796,"props":1110,"children":1111},{"style":809},[1112],{"type":510,"value":885},{"type":504,"tag":796,"props":1114,"children":1115},{"style":824},[1116],{"type":510,"value":1117},"\"web\"",{"type":504,"tag":796,"props":1119,"children":1120},{"style":809},[1121],{"type":510,"value":895},{"type":504,"tag":796,"props":1123,"children":1124},{"class":798,"line":919},[1125,1130],{"type":504,"tag":796,"props":1126,"children":1127},{"style":877},[1128],{"type":510,"value":1129},"  \"dependencies\"",{"type":504,"tag":796,"props":1131,"children":1132},{"style":809},[1133],{"type":510,"value":930},{"type":504,"tag":796,"props":1135,"children":1136},{"class":798,"line":933},[1137,1142,1146,1151],{"type":504,"tag":796,"props":1138,"children":1139},{"style":877},[1140],{"type":510,"value":1141},"    \"ui\"",{"type":504,"tag":796,"props":1143,"children":1144},{"style":809},[1145],{"type":510,"value":885},{"type":504,"tag":796,"props":1147,"children":1148},{"style":824},[1149],{"type":510,"value":1150},"\"workspace:*\"",{"type":504,"tag":796,"props":1152,"children":1153},{"style":956},[1154],{"type":510,"value":1155}," \u002F\u002F \"workspace:*\" 会自动链接到本地的 ui 包\n",{"type":504,"tag":796,"props":1157,"children":1158},{"class":798,"line":962},[1159],{"type":504,"tag":796,"props":1160,"children":1161},{"style":809},[1162],{"type":510,"value":1044},{"type":504,"tag":796,"props":1164,"children":1165},{"class":798,"line":985},[1166],{"type":504,"tag":796,"props":1167,"children":1168},{"style":809},[1169],{"type":510,"value":1053},{"type":504,"tag":1171,"props":1172,"children":1173},"br",{},[],{"type":510,"value":1175},"当你运行 ",{"type":504,"tag":559,"props":1177,"children":1179},{"className":1178},[],[1180],{"type":510,"value":1181},"pnpm install",{"type":510,"value":1183}," 时，",{"type":504,"tag":559,"props":1185,"children":1187},{"className":1186},[],[1188],{"type":510,"value":630},{"type":510,"value":1190}," 会在 ",{"type":504,"tag":559,"props":1192,"children":1194},{"className":1193},[],[1195],{"type":510,"value":1196},"apps\u002Fweb\u002Fnode_modules",{"type":510,"value":1198}," 中创建一个指向 ",{"type":504,"tag":559,"props":1200,"children":1202},{"className":1201},[],[1203],{"type":510,"value":1077},{"type":510,"value":1205}," 的符号链接。你在 ",{"type":504,"tag":559,"props":1207,"children":1209},{"className":1208},[],[1210],{"type":510,"value":564},{"type":510,"value":1212}," 包中的任何修改都会",{"type":504,"tag":520,"props":1214,"children":1215},{},[1216],{"type":510,"value":1217},"立即",{"type":510,"value":1219},"反映在 ",{"type":504,"tag":559,"props":1221,"children":1223},{"className":1222},[],[1224],{"type":510,"value":1225},"web",{"type":510,"value":1227}," 应用中，无需重新发布或链接。",{"type":504,"tag":528,"props":1229,"children":1230},{},[],{"type":504,"tag":532,"props":1232,"children":1234},{"id":1233},"_3-高效任务编排turborepo",[1235],{"type":510,"value":1236},"3. 高效任务编排：Turborepo",{"type":504,"tag":516,"props":1238,"children":1239},{},[1240,1242,1247],{"type":510,"value":1241},"如果你的 Monorepo 很大，每次都重新构建和测试所有的包会非常耗时。",{"type":504,"tag":520,"props":1243,"children":1244},{},[1245],{"type":510,"value":1246},"Turborepo",{"type":510,"value":1248}," 就是解决这个问题的利器。",{"type":504,"tag":642,"props":1250,"children":1252},{"id":1251},"a-核心特性",[1253],{"type":510,"value":1254},"A. 核心特性",{"type":504,"tag":747,"props":1256,"children":1257},{},[1258,1283,1337],{"type":504,"tag":548,"props":1259,"children":1260},{},[1261,1266,1268,1274,1275,1281],{"type":504,"tag":520,"props":1262,"children":1263},{},[1264],{"type":510,"value":1265},"远程缓存 (Remote Caching)",{"type":510,"value":1267},"：Turborepo 会缓存你的任务（如 ",{"type":504,"tag":559,"props":1269,"children":1271},{"className":1270},[],[1272],{"type":510,"value":1273},"build",{"type":510,"value":953},{"type":504,"tag":559,"props":1276,"children":1278},{"className":1277},[],[1279],{"type":510,"value":1280},"test",{"type":510,"value":1282},"）的输出。当你和你的团队成员运行任务时，如果输入（代码、依赖、环境变量）没有改变，Turborepo 会直接从缓存中拉取结果，而不是在本地重新执行。这使得 CI 和本地构建速度快得惊人。",{"type":504,"tag":548,"props":1284,"children":1285},{},[1286,1291,1293,1299,1301,1307,1309,1314,1316,1321,1323,1328,1330,1335],{"type":504,"tag":520,"props":1287,"children":1288},{},[1289],{"type":510,"value":1290},"任务流水线 (Task Pipelines)",{"type":510,"value":1292},"：在 ",{"type":504,"tag":559,"props":1294,"children":1296},{"className":1295},[],[1297],{"type":510,"value":1298},"turbo.json",{"type":510,"value":1300}," 中定义任务之间的依赖关系。例如，",{"type":504,"tag":559,"props":1302,"children":1304},{"className":1303},[],[1305],{"type":510,"value":1306},"deploy",{"type":510,"value":1308}," 依赖于 ",{"type":504,"tag":559,"props":1310,"children":1312},{"className":1311},[],[1313],{"type":510,"value":1273},{"type":510,"value":1315}," 和 ",{"type":504,"tag":559,"props":1317,"children":1319},{"className":1318},[],[1320],{"type":510,"value":1280},{"type":510,"value":1322},"，而 ",{"type":504,"tag":559,"props":1324,"children":1326},{"className":1325},[],[1327],{"type":510,"value":1273},{"type":510,"value":1329}," 又依赖于其内部依赖包的 ",{"type":504,"tag":559,"props":1331,"children":1333},{"className":1332},[],[1334],{"type":510,"value":1273},{"type":510,"value":1336},"。Turborepo 会以最高效的并行度来执行这个任务图。",{"type":504,"tag":548,"props":1338,"children":1339},{},[1340,1345],{"type":504,"tag":520,"props":1341,"children":1342},{},[1343],{"type":510,"value":1344},"智能感知 (Scoped Tasks)",{"type":510,"value":1346},"：Turborepo 知道哪些包的代码发生了变化，只会重新运行受影响的包及其依赖项的任务。",{"type":504,"tag":642,"props":1348,"children":1350},{"id":1349},"b-如何设置-1",[1351],{"type":510,"value":745},{"type":504,"tag":747,"props":1353,"children":1354},{},[1355,1406,1775],{"type":504,"tag":548,"props":1356,"children":1357},{},[1358,1363,1364],{"type":504,"tag":520,"props":1359,"children":1360},{},[1361],{"type":510,"value":1362},"安装 Turborepo",{"type":510,"value":759},{"type":504,"tag":761,"props":1365,"children":1369},{"className":1366,"code":1367,"language":1368,"meta":769,"style":769},"language-bash shiki shiki-themes github-light github-dark","pnpm add turbo --save-dev -w # -w 表示安装在根工作区\n","bash",[1370],{"type":504,"tag":559,"props":1371,"children":1372},{"__ignoreMap":769},[1373],{"type":504,"tag":796,"props":1374,"children":1375},{"class":798,"line":799},[1376,1381,1386,1391,1396,1401],{"type":504,"tag":796,"props":1377,"children":1379},{"style":1378},"--shiki-default:#6F42C1;--shiki-dark:#B392F0",[1380],{"type":510,"value":630},{"type":504,"tag":796,"props":1382,"children":1383},{"style":824},[1384],{"type":510,"value":1385}," add",{"type":504,"tag":796,"props":1387,"children":1388},{"style":824},[1389],{"type":510,"value":1390}," turbo",{"type":504,"tag":796,"props":1392,"children":1393},{"style":877},[1394],{"type":510,"value":1395}," --save-dev",{"type":504,"tag":796,"props":1397,"children":1398},{"style":877},[1399],{"type":510,"value":1400}," -w",{"type":504,"tag":796,"props":1402,"children":1403},{"style":956},[1404],{"type":510,"value":1405}," # -w 表示安装在根工作区\n",{"type":504,"tag":548,"props":1407,"children":1408},{},[1409,1419,1420,1747],{"type":504,"tag":520,"props":1410,"children":1411},{},[1412,1414],{"type":510,"value":1413},"创建 ",{"type":504,"tag":559,"props":1415,"children":1417},{"className":1416},[],[1418],{"type":510,"value":1298},{"type":510,"value":759},{"type":504,"tag":761,"props":1421,"children":1423},{"className":857,"code":1422,"language":859,"meta":769,"style":769},"\u002F\u002F turbo.json\n{\n  \"$schema\": \"https:\u002F\u002Fturbo.build\u002Fschema.json\",\n  \"baseBranch\": \"origin\u002Fmain\",\n  \"pipeline\": {\n    \"build\": {\n      \u002F\u002F \"build\" 任务依赖于所有内部依赖项的 \"build\" 任务\n      \"dependsOn\": [\"^build\"],\n      \u002F\u002F \"build\" 任务的输出是 .next, dist 和 build 目录\n      \"outputs\": [\".next\u002F**\", \"dist\u002F**\", \"build\u002F**\"]\n    },\n    \"lint\": {\n      \"outputs\": [] \u002F\u002F lint 不产生持久化文件\n    },\n    \"test\": {\n      \"dependsOn\": [\"build\"],\n      \"outputs\": []\n    },\n    \"dev\": {\n      \"cache\": false \u002F\u002F 开发服务器不应该被缓存\n    }\n  }\n}\n",[1424],{"type":504,"tag":559,"props":1425,"children":1426},{"__ignoreMap":769},[1427,1435,1442,1463,1484,1496,1507,1515,1538,1546,1586,1594,1606,1624,1632,1645,1666,1679,1687,1699,1722,1731,1739],{"type":504,"tag":796,"props":1428,"children":1429},{"class":798,"line":799},[1430],{"type":504,"tag":796,"props":1431,"children":1432},{"style":956},[1433],{"type":510,"value":1434},"\u002F\u002F turbo.json\n",{"type":504,"tag":796,"props":1436,"children":1437},{"class":798,"line":815},[1438],{"type":504,"tag":796,"props":1439,"children":1440},{"style":809},[1441],{"type":510,"value":871},{"type":504,"tag":796,"props":1443,"children":1444},{"class":798,"line":830},[1445,1450,1454,1459],{"type":504,"tag":796,"props":1446,"children":1447},{"style":877},[1448],{"type":510,"value":1449},"  \"$schema\"",{"type":504,"tag":796,"props":1451,"children":1452},{"style":809},[1453],{"type":510,"value":885},{"type":504,"tag":796,"props":1455,"children":1456},{"style":824},[1457],{"type":510,"value":1458},"\"https:\u002F\u002Fturbo.build\u002Fschema.json\"",{"type":504,"tag":796,"props":1460,"children":1461},{"style":809},[1462],{"type":510,"value":895},{"type":504,"tag":796,"props":1464,"children":1465},{"class":798,"line":919},[1466,1471,1475,1480],{"type":504,"tag":796,"props":1467,"children":1468},{"style":877},[1469],{"type":510,"value":1470},"  \"baseBranch\"",{"type":504,"tag":796,"props":1472,"children":1473},{"style":809},[1474],{"type":510,"value":885},{"type":504,"tag":796,"props":1476,"children":1477},{"style":824},[1478],{"type":510,"value":1479},"\"origin\u002Fmain\"",{"type":504,"tag":796,"props":1481,"children":1482},{"style":809},[1483],{"type":510,"value":895},{"type":504,"tag":796,"props":1485,"children":1486},{"class":798,"line":933},[1487,1492],{"type":504,"tag":796,"props":1488,"children":1489},{"style":877},[1490],{"type":510,"value":1491},"  \"pipeline\"",{"type":504,"tag":796,"props":1493,"children":1494},{"style":809},[1495],{"type":510,"value":930},{"type":504,"tag":796,"props":1497,"children":1498},{"class":798,"line":962},[1499,1503],{"type":504,"tag":796,"props":1500,"children":1501},{"style":877},[1502],{"type":510,"value":968},{"type":504,"tag":796,"props":1504,"children":1505},{"style":809},[1506],{"type":510,"value":930},{"type":504,"tag":796,"props":1508,"children":1509},{"class":798,"line":985},[1510],{"type":504,"tag":796,"props":1511,"children":1512},{"style":956},[1513],{"type":510,"value":1514},"      \u002F\u002F \"build\" 任务依赖于所有内部依赖项的 \"build\" 任务\n",{"type":504,"tag":796,"props":1516,"children":1517},{"class":798,"line":994},[1518,1523,1528,1533],{"type":504,"tag":796,"props":1519,"children":1520},{"style":877},[1521],{"type":510,"value":1522},"      \"dependsOn\"",{"type":504,"tag":796,"props":1524,"children":1525},{"style":809},[1526],{"type":510,"value":1527},": [",{"type":504,"tag":796,"props":1529,"children":1530},{"style":824},[1531],{"type":510,"value":1532},"\"^build\"",{"type":504,"tag":796,"props":1534,"children":1535},{"style":809},[1536],{"type":510,"value":1537},"],\n",{"type":504,"tag":796,"props":1539,"children":1540},{"class":798,"line":1007},[1541],{"type":504,"tag":796,"props":1542,"children":1543},{"style":956},[1544],{"type":510,"value":1545},"      \u002F\u002F \"build\" 任务的输出是 .next, dist 和 build 目录\n",{"type":504,"tag":796,"props":1547,"children":1548},{"class":798,"line":1029},[1549,1554,1558,1563,1567,1572,1576,1581],{"type":504,"tag":796,"props":1550,"children":1551},{"style":877},[1552],{"type":510,"value":1553},"      \"outputs\"",{"type":504,"tag":796,"props":1555,"children":1556},{"style":809},[1557],{"type":510,"value":1527},{"type":504,"tag":796,"props":1559,"children":1560},{"style":824},[1561],{"type":510,"value":1562},"\".next\u002F**\"",{"type":504,"tag":796,"props":1564,"children":1565},{"style":809},[1566],{"type":510,"value":953},{"type":504,"tag":796,"props":1568,"children":1569},{"style":824},[1570],{"type":510,"value":1571},"\"dist\u002F**\"",{"type":504,"tag":796,"props":1573,"children":1574},{"style":809},[1575],{"type":510,"value":953},{"type":504,"tag":796,"props":1577,"children":1578},{"style":824},[1579],{"type":510,"value":1580},"\"build\u002F**\"",{"type":504,"tag":796,"props":1582,"children":1583},{"style":809},[1584],{"type":510,"value":1585},"]\n",{"type":504,"tag":796,"props":1587,"children":1588},{"class":798,"line":1038},[1589],{"type":504,"tag":796,"props":1590,"children":1591},{"style":809},[1592],{"type":510,"value":1593},"    },\n",{"type":504,"tag":796,"props":1595,"children":1596},{"class":798,"line":1047},[1597,1602],{"type":504,"tag":796,"props":1598,"children":1599},{"style":877},[1600],{"type":510,"value":1601},"    \"lint\"",{"type":504,"tag":796,"props":1603,"children":1604},{"style":809},[1605],{"type":510,"value":930},{"type":504,"tag":796,"props":1607,"children":1609},{"class":798,"line":1608},13,[1610,1614,1619],{"type":504,"tag":796,"props":1611,"children":1612},{"style":877},[1613],{"type":510,"value":1553},{"type":504,"tag":796,"props":1615,"children":1616},{"style":809},[1617],{"type":510,"value":1618},": [] ",{"type":504,"tag":796,"props":1620,"children":1621},{"style":956},[1622],{"type":510,"value":1623},"\u002F\u002F lint 不产生持久化文件\n",{"type":504,"tag":796,"props":1625,"children":1627},{"class":798,"line":1626},14,[1628],{"type":504,"tag":796,"props":1629,"children":1630},{"style":809},[1631],{"type":510,"value":1593},{"type":504,"tag":796,"props":1633,"children":1635},{"class":798,"line":1634},15,[1636,1641],{"type":504,"tag":796,"props":1637,"children":1638},{"style":877},[1639],{"type":510,"value":1640},"    \"test\"",{"type":504,"tag":796,"props":1642,"children":1643},{"style":809},[1644],{"type":510,"value":930},{"type":504,"tag":796,"props":1646,"children":1648},{"class":798,"line":1647},16,[1649,1653,1657,1662],{"type":504,"tag":796,"props":1650,"children":1651},{"style":877},[1652],{"type":510,"value":1522},{"type":504,"tag":796,"props":1654,"children":1655},{"style":809},[1656],{"type":510,"value":1527},{"type":504,"tag":796,"props":1658,"children":1659},{"style":824},[1660],{"type":510,"value":1661},"\"build\"",{"type":504,"tag":796,"props":1663,"children":1664},{"style":809},[1665],{"type":510,"value":1537},{"type":504,"tag":796,"props":1667,"children":1669},{"class":798,"line":1668},17,[1670,1674],{"type":504,"tag":796,"props":1671,"children":1672},{"style":877},[1673],{"type":510,"value":1553},{"type":504,"tag":796,"props":1675,"children":1676},{"style":809},[1677],{"type":510,"value":1678},": []\n",{"type":504,"tag":796,"props":1680,"children":1682},{"class":798,"line":1681},18,[1683],{"type":504,"tag":796,"props":1684,"children":1685},{"style":809},[1686],{"type":510,"value":1593},{"type":504,"tag":796,"props":1688,"children":1690},{"class":798,"line":1689},19,[1691,1695],{"type":504,"tag":796,"props":1692,"children":1693},{"style":877},[1694],{"type":510,"value":939},{"type":504,"tag":796,"props":1696,"children":1697},{"style":809},[1698],{"type":510,"value":930},{"type":504,"tag":796,"props":1700,"children":1702},{"class":798,"line":1701},20,[1703,1708,1712,1717],{"type":504,"tag":796,"props":1704,"children":1705},{"style":877},[1706],{"type":510,"value":1707},"      \"cache\"",{"type":504,"tag":796,"props":1709,"children":1710},{"style":809},[1711],{"type":510,"value":885},{"type":504,"tag":796,"props":1713,"children":1714},{"style":877},[1715],{"type":510,"value":1716},"false",{"type":504,"tag":796,"props":1718,"children":1719},{"style":956},[1720],{"type":510,"value":1721}," \u002F\u002F 开发服务器不应该被缓存\n",{"type":504,"tag":796,"props":1723,"children":1725},{"class":798,"line":1724},21,[1726],{"type":504,"tag":796,"props":1727,"children":1728},{"style":809},[1729],{"type":510,"value":1730},"    }\n",{"type":504,"tag":796,"props":1732,"children":1734},{"class":798,"line":1733},22,[1735],{"type":504,"tag":796,"props":1736,"children":1737},{"style":809},[1738],{"type":510,"value":1044},{"type":504,"tag":796,"props":1740,"children":1742},{"class":798,"line":1741},23,[1743],{"type":504,"tag":796,"props":1744,"children":1745},{"style":809},[1746],{"type":510,"value":1053},{"type":504,"tag":544,"props":1748,"children":1749},{},[1750],{"type":504,"tag":548,"props":1751,"children":1752},{},[1753,1759,1760,1766,1768,1773],{"type":504,"tag":559,"props":1754,"children":1756},{"className":1755},[],[1757],{"type":510,"value":1758},"^build",{"type":510,"value":885},{"type":504,"tag":559,"props":1761,"children":1763},{"className":1762},[],[1764],{"type":510,"value":1765},"^",{"type":510,"value":1767}," 符号表示“拓扑依赖”，即“我所依赖的所有包的 ",{"type":504,"tag":559,"props":1769,"children":1771},{"className":1770},[],[1772],{"type":510,"value":1273},{"type":510,"value":1774}," 任务”。",{"type":504,"tag":548,"props":1776,"children":1777},{},[1778,1790,1792,1798,1800],{"type":504,"tag":520,"props":1779,"children":1780},{},[1781,1783,1788],{"type":510,"value":1782},"更新 ",{"type":504,"tag":559,"props":1784,"children":1786},{"className":1785},[],[1787],{"type":510,"value":737},{"type":510,"value":1789}," 脚本",{"type":510,"value":1791},"：使用 ",{"type":504,"tag":559,"props":1793,"children":1795},{"className":1794},[],[1796],{"type":510,"value":1797},"turbo",{"type":510,"value":1799}," 来运行你的脚本。",{"type":504,"tag":761,"props":1801,"children":1803},{"className":857,"code":1802,"language":859,"meta":769,"style":769},"\u002F\u002F package.json\n{\n  \"scripts\": {\n    \"dev\": \"turbo run dev\",\n    \"build\": \"turbo run build\",\n    \"test\": \"turbo run test\",\n    \"lint\": \"turbo run lint\"\n  }\n}\n",[1804],{"type":504,"tag":559,"props":1805,"children":1806},{"__ignoreMap":769},[1807,1815,1822,1833,1853,1873,1893,1909,1916],{"type":504,"tag":796,"props":1808,"children":1809},{"class":798,"line":799},[1810],{"type":504,"tag":796,"props":1811,"children":1812},{"style":956},[1813],{"type":510,"value":1814},"\u002F\u002F package.json\n",{"type":504,"tag":796,"props":1816,"children":1817},{"class":798,"line":815},[1818],{"type":504,"tag":796,"props":1819,"children":1820},{"style":809},[1821],{"type":510,"value":871},{"type":504,"tag":796,"props":1823,"children":1824},{"class":798,"line":830},[1825,1829],{"type":504,"tag":796,"props":1826,"children":1827},{"style":877},[1828],{"type":510,"value":925},{"type":504,"tag":796,"props":1830,"children":1831},{"style":809},[1832],{"type":510,"value":930},{"type":504,"tag":796,"props":1834,"children":1835},{"class":798,"line":919},[1836,1840,1844,1849],{"type":504,"tag":796,"props":1837,"children":1838},{"style":877},[1839],{"type":510,"value":939},{"type":504,"tag":796,"props":1841,"children":1842},{"style":809},[1843],{"type":510,"value":885},{"type":504,"tag":796,"props":1845,"children":1846},{"style":824},[1847],{"type":510,"value":1848},"\"turbo run dev\"",{"type":504,"tag":796,"props":1850,"children":1851},{"style":809},[1852],{"type":510,"value":895},{"type":504,"tag":796,"props":1854,"children":1855},{"class":798,"line":933},[1856,1860,1864,1869],{"type":504,"tag":796,"props":1857,"children":1858},{"style":877},[1859],{"type":510,"value":968},{"type":504,"tag":796,"props":1861,"children":1862},{"style":809},[1863],{"type":510,"value":885},{"type":504,"tag":796,"props":1865,"children":1866},{"style":824},[1867],{"type":510,"value":1868},"\"turbo run build\"",{"type":504,"tag":796,"props":1870,"children":1871},{"style":809},[1872],{"type":510,"value":895},{"type":504,"tag":796,"props":1874,"children":1875},{"class":798,"line":962},[1876,1880,1884,1889],{"type":504,"tag":796,"props":1877,"children":1878},{"style":877},[1879],{"type":510,"value":1640},{"type":504,"tag":796,"props":1881,"children":1882},{"style":809},[1883],{"type":510,"value":885},{"type":504,"tag":796,"props":1885,"children":1886},{"style":824},[1887],{"type":510,"value":1888},"\"turbo run test\"",{"type":504,"tag":796,"props":1890,"children":1891},{"style":809},[1892],{"type":510,"value":895},{"type":504,"tag":796,"props":1894,"children":1895},{"class":798,"line":985},[1896,1900,1904],{"type":504,"tag":796,"props":1897,"children":1898},{"style":877},[1899],{"type":510,"value":1601},{"type":504,"tag":796,"props":1901,"children":1902},{"style":809},[1903],{"type":510,"value":885},{"type":504,"tag":796,"props":1905,"children":1906},{"style":824},[1907],{"type":510,"value":1908},"\"turbo run lint\"\n",{"type":504,"tag":796,"props":1910,"children":1911},{"class":798,"line":994},[1912],{"type":504,"tag":796,"props":1913,"children":1914},{"style":809},[1915],{"type":510,"value":1044},{"type":504,"tag":796,"props":1917,"children":1918},{"class":798,"line":1007},[1919],{"type":504,"tag":796,"props":1920,"children":1921},{"style":809},[1922],{"type":510,"value":1053},{"type":504,"tag":516,"props":1924,"children":1925},{},[1926,1928,1934,1935,1940],{"type":510,"value":1927},"现在，当你运行 ",{"type":504,"tag":559,"props":1929,"children":1931},{"className":1930},[],[1932],{"type":510,"value":1933},"pnpm build",{"type":510,"value":1183},{"type":504,"tag":559,"props":1936,"children":1938},{"className":1937},[],[1939],{"type":510,"value":1797},{"type":510,"value":1941}," 会接管一切：它会分析你的依赖图，找出哪些包需要构建，并行地执行它们，缓存结果，并跳过所有未发生变化的工作。",{"type":504,"tag":528,"props":1943,"children":1944},{},[],{"type":504,"tag":532,"props":1946,"children":1948},{"id":1947},"_4-依赖治理",[1949],{"type":510,"value":1950},"4. 依赖治理",{"type":504,"tag":516,"props":1952,"children":1953},{},[1954],{"type":510,"value":1955},"Monorepo 也带来了依赖治理的挑战。",{"type":504,"tag":544,"props":1957,"children":1958},{},[1959,1999,2016],{"type":504,"tag":548,"props":1960,"children":1961},{},[1962,1967,1969,1974,1976,1982,1983,1989,1991,1997],{"type":504,"tag":520,"props":1963,"children":1964},{},[1965],{"type":510,"value":1966},"版本统一",{"type":510,"value":1968},"：尽可能在根 ",{"type":504,"tag":559,"props":1970,"children":1972},{"className":1971},[],[1973],{"type":510,"value":737},{"type":510,"value":1975}," 中定义核心依赖（如 ",{"type":504,"tag":559,"props":1977,"children":1979},{"className":1978},[],[1980],{"type":510,"value":1981},"react",{"type":510,"value":953},{"type":504,"tag":559,"props":1984,"children":1986},{"className":1985},[],[1987],{"type":510,"value":1988},"typescript",{"type":510,"value":1990},"）的版本，所有子包通过 ",{"type":504,"tag":559,"props":1992,"children":1994},{"className":1993},[],[1995],{"type":510,"value":1996},"peerDependencies",{"type":510,"value":1998}," 继承。",{"type":504,"tag":548,"props":2000,"children":2001},{},[2002,2007,2008,2014],{"type":504,"tag":520,"props":2003,"children":2004},{},[2005],{"type":510,"value":2006},"依赖更新",{"type":510,"value":1791},{"type":504,"tag":559,"props":2009,"children":2011},{"className":2010},[],[2012],{"type":510,"value":2013},"pnpm up -r --latest",{"type":510,"value":2015}," 来递归地更新所有包的依赖项。",{"type":504,"tag":548,"props":2017,"children":2018},{},[2019,2024,2026,2032,2034,2040],{"type":504,"tag":520,"props":2020,"children":2021},{},[2022],{"type":510,"value":2023},"循环依赖",{"type":510,"value":2025},"：Monorepo 中很容易出现循环依赖（A 依赖 B，B 又依赖 A）。使用 ",{"type":504,"tag":559,"props":2027,"children":2029},{"className":2028},[],[2030],{"type":510,"value":2031},"madge -c",{"type":510,"value":2033}," 或 ",{"type":504,"tag":559,"props":2035,"children":2037},{"className":2036},[],[2038],{"type":510,"value":2039},"nx graph",{"type":510,"value":2041}," 等工具来检测和可视化依赖关系，及时发现并解决循环依赖问题。",{"type":504,"tag":528,"props":2043,"children":2044},{},[],{"type":504,"tag":532,"props":2046,"children":2048},{"id":2047},"_5-关联阅读",[2049],{"type":510,"value":2050},"5. 关联阅读",{"type":504,"tag":544,"props":2052,"children":2053},{},[2054,2072,2088],{"type":504,"tag":548,"props":2055,"children":2056},{},[2057,2062,2063],{"type":504,"tag":520,"props":2058,"children":2059},{},[2060],{"type":510,"value":2061},"Turborepo 官方文档",{"type":510,"value":885},{"type":504,"tag":2064,"props":2065,"children":2069},"a",{"href":2066,"rel":2067},"https:\u002F\u002Fturbo.build\u002Frepo\u002Fdocs",[2068],"nofollow",[2070],{"type":510,"value":2071},"turbo.build\u002Frepo\u002Fdocs",{"type":504,"tag":548,"props":2073,"children":2074},{},[2075,2080,2081],{"type":504,"tag":520,"props":2076,"children":2077},{},[2078],{"type":510,"value":2079},"pnpm 官方文档",{"type":510,"value":885},{"type":504,"tag":2064,"props":2082,"children":2085},{"href":2083,"rel":2084},"https:\u002F\u002Fpnpm.io\u002Fworkspaces",[2068],[2086],{"type":510,"value":2087},"pnpm.io\u002Fworkspaces",{"type":504,"tag":548,"props":2089,"children":2090},{},[2091,2096,2097],{"type":504,"tag":520,"props":2092,"children":2093},{},[2094],{"type":510,"value":2095},"Monorepo.tools",{"type":510,"value":885},{"type":504,"tag":2064,"props":2098,"children":2101},{"href":2099,"rel":2100},"https:\u002F\u002Fmonorepo.tools\u002F",[2068],[2102],{"type":510,"value":2103},"A collection of tools for monorepos",{"type":504,"tag":2105,"props":2106,"children":2107},"style",{},[2108],{"type":510,"value":2109},"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":769,"searchDepth":815,"depth":815,"links":2111},[2112,2113,2117,2121,2122],{"id":534,"depth":815,"text":537},{"id":618,"depth":815,"text":621,"children":2114},[2115,2116],{"id":644,"depth":830,"text":647},{"id":742,"depth":830,"text":745},{"id":1233,"depth":815,"text":1236,"children":2118},[2119,2120],{"id":1251,"depth":830,"text":1254},{"id":1349,"depth":830,"text":745},{"id":1947,"depth":815,"text":1950},{"id":2047,"depth":815,"text":2050},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":2124},"\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":2126},"\u003Cpath fill=\"currentColor\" d=\"M3 4h18v2H3zm0 7h12v2H3zm0 7h18v2H3z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":2128},"\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":2130,"height":2130,"rotate":4,"vFlip":6,"hFlip":6,"body":2131},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>"]