[{"data":1,"prerenderedAt":2800},["ShallowReactive",2],{"article-/topics/frontend/visual-editor-core-technology-guide":3,"related-frontend":500,"content-query-jmEMxfvVa6":2425},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"topic":5,"author":11,"tags":12,"image":18,"imageQuery":19,"pexelsPhotoId":20,"pexelsUrl":21,"featured":6,"readingTime":22,"body":23,"_type":494,"_id":495,"_source":496,"_file":497,"_stem":498,"_extension":499},"/topics/frontend/visual-editor-core-technology-guide","frontend",false,"","可视化编辑器核心技术：从画布交互到发布运行时的关键能力","可视化编辑器的难点不在拖拽动作本身，而在模型同步、选区管理、撤销重做、样式系统和导出运行时。本文系统拆解编辑器最核心的技术能力与架构边界。","2026-04-23","HTMLPAGE 团队",[13,14,15,16,17],"Visual Editor","Frontend Architecture","Drag and Drop","Runtime","Low Code","/images/topics/frontend/visual-editor-core-technology-guide.jpg","visual website editor interface on monitor design workspace",6804581,"https://www.pexels.com/photo/workstation-while-working-on-the-webpage-6804581/",15,{"type":24,"children":25,"toc":482},"root",[26,34,39,69,74,81,86,91,96,119,124,130,135,158,163,181,186,192,197,215,220,248,253,259,264,269,292,297,303,308,313,336,341,347,352,370,375,380,398,403,408,436,441,446,451],{"type":27,"tag":28,"props":29,"children":30},"element","p",{},[31],{"type":32,"value":33},"text","可视化编辑器最容易被低估的地方，是外部看起来只是“能拖动组件”。",{"type":27,"tag":28,"props":35,"children":36},{},[37],{"type":32,"value":38},"但真正落到工程实现，团队很快会发现它同时是一套：",{"type":27,"tag":40,"props":41,"children":42},"ul",{},[43,49,54,59,64],{"type":27,"tag":44,"props":45,"children":46},"li",{},[47],{"type":32,"value":48},"文档模型系统",{"type":27,"tag":44,"props":50,"children":51},{},[52],{"type":32,"value":53},"交互状态系统",{"type":27,"tag":44,"props":55,"children":56},{},[57],{"type":32,"value":58},"组件渲染系统",{"type":27,"tag":44,"props":60,"children":61},{},[62],{"type":32,"value":63},"样式与布局系统",{"type":27,"tag":44,"props":65,"children":66},{},[67],{"type":32,"value":68},"发布与运行时系统",{"type":27,"tag":28,"props":70,"children":71},{},[72],{"type":32,"value":73},"拖拽只是用户能看到的一小部分。真正决定编辑器是否可用的，是这些系统能不能长期保持同步和可控。",{"type":27,"tag":75,"props":76,"children":78},"h2",{"id":77},"编辑器的第一原则不是交互顺滑而是模型稳定",[79],{"type":32,"value":80},"编辑器的第一原则不是交互顺滑，而是模型稳定",{"type":27,"tag":28,"props":82,"children":83},{},[84],{"type":32,"value":85},"很多编辑器第一版会直接操作 DOM：拖一拖、改一改、再把结果序列化保存。",{"type":27,"tag":28,"props":87,"children":88},{},[89],{"type":32,"value":90},"这种方式启动快，但很难支撑复杂场景。原因很简单：DOM 只是结果，不是可治理的数据模型。",{"type":27,"tag":28,"props":92,"children":93},{},[94],{"type":32,"value":95},"更稳的做法是先定义文档模型：",{"type":27,"tag":40,"props":97,"children":98},{},[99,104,109,114],{"type":27,"tag":44,"props":100,"children":101},{},[102],{"type":32,"value":103},"页面由哪些节点组成",{"type":27,"tag":44,"props":105,"children":106},{},[107],{"type":32,"value":108},"节点有哪些可编辑属性",{"type":27,"tag":44,"props":110,"children":111},{},[112],{"type":32,"value":113},"布局、样式、事件各自存在哪一层",{"type":27,"tag":44,"props":115,"children":116},{},[117],{"type":32,"value":118},"节点之间有哪些父子约束和区域边界",{"type":27,"tag":28,"props":120,"children":121},{},[122],{"type":32,"value":123},"只要文档模型稳定，画布渲染、属性面板、图层树、历史记录和导出逻辑才有共同语言。",{"type":27,"tag":75,"props":125,"children":127},{"id":126},"选区拖拽和对齐辅助线是同一个状态问题",[128],{"type":32,"value":129},"选区、拖拽和对齐辅助线是同一个状态问题",{"type":27,"tag":28,"props":131,"children":132},{},[133],{"type":32,"value":134},"很多团队会把这些交互拆成单独功能开发，但本质上它们都依赖同一套编辑状态：",{"type":27,"tag":40,"props":136,"children":137},{},[138,143,148,153],{"type":27,"tag":44,"props":139,"children":140},{},[141],{"type":32,"value":142},"当前选中节点是谁",{"type":27,"tag":44,"props":144,"children":145},{},[146],{"type":32,"value":147},"节点在画布中的定位信息是什么",{"type":27,"tag":44,"props":149,"children":150},{},[151],{"type":32,"value":152},"拖拽目标容器是否合法",{"type":27,"tag":44,"props":154,"children":155},{},[156],{"type":32,"value":157},"对齐线和吸附规则如何计算",{"type":27,"tag":28,"props":159,"children":160},{},[161],{"type":32,"value":162},"如果没有统一状态层，就会出现典型问题：",{"type":27,"tag":40,"props":164,"children":165},{},[166,171,176],{"type":27,"tag":44,"props":167,"children":168},{},[169],{"type":32,"value":170},"图层树选中一个节点，画布没同步高亮",{"type":27,"tag":44,"props":172,"children":173},{},[174],{"type":32,"value":175},"拖拽结束后属性面板仍显示旧数据",{"type":27,"tag":44,"props":177,"children":178},{},[179],{"type":32,"value":180},"组件嵌套后容器判断失真",{"type":27,"tag":28,"props":182,"children":183},{},[184],{"type":32,"value":185},"所以编辑器的交互层一定要把“选区、拖拽、悬停、缩放、参考线”当作同一套状态机来管理，而不是分散在不同组件里各写一套逻辑。",{"type":27,"tag":75,"props":187,"children":189},{"id":188},"撤销重做的关键不是快照而是可恢复操作",[190],{"type":32,"value":191},"撤销重做的关键不是快照，而是可恢复操作",{"type":27,"tag":28,"props":193,"children":194},{},[195],{"type":32,"value":196},"编辑器只要进入真实使用，很快就会遇到撤销重做需求。最粗暴的方法是整份 schema 做快照，但数据一大就会出问题：",{"type":27,"tag":40,"props":198,"children":199},{},[200,205,210],{"type":27,"tag":44,"props":201,"children":202},{},[203],{"type":32,"value":204},"内存占用急速上升",{"type":27,"tag":44,"props":206,"children":207},{},[208],{"type":32,"value":209},"高频操作卡顿",{"type":27,"tag":44,"props":211,"children":212},{},[213],{"type":32,"value":214},"多人协作时冲突难以处理",{"type":27,"tag":28,"props":216,"children":217},{},[218],{"type":32,"value":219},"更可持续的方案通常是操作日志模型：",{"type":27,"tag":40,"props":221,"children":222},{},[223,228,233,238,243],{"type":27,"tag":44,"props":224,"children":225},{},[226],{"type":32,"value":227},"新增节点",{"type":27,"tag":44,"props":229,"children":230},{},[231],{"type":32,"value":232},"删除节点",{"type":27,"tag":44,"props":234,"children":235},{},[236],{"type":32,"value":237},"修改属性",{"type":27,"tag":44,"props":239,"children":240},{},[241],{"type":32,"value":242},"调整层级",{"type":27,"tag":44,"props":244,"children":245},{},[246],{"type":32,"value":247},"批量变更样式",{"type":27,"tag":28,"props":249,"children":250},{},[251],{"type":32,"value":252},"这样既更容易做增量回滚，也更适合后续接协作和审计。",{"type":27,"tag":75,"props":254,"children":256},{"id":255},"样式系统要从可编辑升级到可约束",[257],{"type":32,"value":258},"样式系统要从“可编辑”升级到“可约束”",{"type":27,"tag":28,"props":260,"children":261},{},[262],{"type":32,"value":263},"可视化编辑器一旦缺少样式约束，很快就会变成“谁都能改，最后谁也管不住”。",{"type":27,"tag":28,"props":265,"children":266},{},[267],{"type":32,"value":268},"所以样式系统不能只是把 CSS 属性搬到面板里，而要建立约束层：",{"type":27,"tag":40,"props":270,"children":271},{},[272,277,282,287],{"type":27,"tag":44,"props":273,"children":274},{},[275],{"type":32,"value":276},"哪些属性开放给业务改",{"type":27,"tag":44,"props":278,"children":279},{},[280],{"type":32,"value":281},"哪些值必须走 design tokens",{"type":27,"tag":44,"props":283,"children":284},{},[285],{"type":32,"value":286},"响应式规则怎么配置",{"type":27,"tag":44,"props":288,"children":289},{},[290],{"type":32,"value":291},"组件默认样式和实例覆盖如何合并",{"type":27,"tag":28,"props":293,"children":294},{},[295],{"type":32,"value":296},"只有这样，页面才不会在快速生产后演变成一堆无法维护的内联样式集合。",{"type":27,"tag":75,"props":298,"children":300},{"id":299},"导出与运行时要提前设计而不是后补",[301],{"type":32,"value":302},"导出与运行时要提前设计，而不是后补",{"type":27,"tag":28,"props":304,"children":305},{},[306],{"type":32,"value":307},"很多编辑器初期只考虑“编辑效果”，等到需要导出源码、发布页面、做在线渲染时才发现架构不支持。",{"type":27,"tag":28,"props":309,"children":310},{},[311],{"type":32,"value":312},"编辑器要尽早回答几个问题：",{"type":27,"tag":40,"props":314,"children":315},{},[316,321,326,331],{"type":27,"tag":44,"props":317,"children":318},{},[319],{"type":32,"value":320},"输出的是 schema、模板代码还是完整站点资源",{"type":27,"tag":44,"props":322,"children":323},{},[324],{"type":32,"value":325},"线上运行时是否依赖编辑器内部组件实现",{"type":27,"tag":44,"props":327,"children":328},{},[329],{"type":32,"value":330},"组件资源如何按需加载",{"type":27,"tag":44,"props":332,"children":333},{},[334],{"type":32,"value":335},"导出后能否脱离平台独立运行",{"type":27,"tag":28,"props":337,"children":338},{},[339],{"type":32,"value":340},"如果这些边界没有提前想好，后面很容易被历史实现锁死。",{"type":27,"tag":75,"props":342,"children":344},{"id":343},"一个常见失败案例编辑器功能很多但每加一个能力都要重构画布",[345],{"type":32,"value":346},"一个常见失败案例：编辑器功能很多，但每加一个能力都要重构画布",{"type":27,"tag":28,"props":348,"children":349},{},[350],{"type":32,"value":351},"这类项目通常前期做得很热闹：",{"type":27,"tag":40,"props":353,"children":354},{},[355,360,365],{"type":27,"tag":44,"props":356,"children":357},{},[358],{"type":32,"value":359},"已经能拖拽",{"type":27,"tag":44,"props":361,"children":362},{},[363],{"type":32,"value":364},"已经能改样式",{"type":27,"tag":44,"props":366,"children":367},{},[368],{"type":32,"value":369},"已经能预览",{"type":27,"tag":28,"props":371,"children":372},{},[373],{"type":32,"value":374},"但等团队要加图层管理、批量操作、协作评论、模板继承时，就发现核心模型太薄，所有功能都直接绑在画布组件上。",{"type":27,"tag":28,"props":376,"children":377},{},[378],{"type":32,"value":379},"结果就是：",{"type":27,"tag":40,"props":381,"children":382},{},[383,388,393],{"type":27,"tag":44,"props":384,"children":385},{},[386],{"type":32,"value":387},"功能迭代速度越来越慢",{"type":27,"tag":44,"props":389,"children":390},{},[391],{"type":32,"value":392},"Bug 只会越修越多",{"type":27,"tag":44,"props":394,"children":395},{},[396],{"type":32,"value":397},"发布链路永远做不稳",{"type":27,"tag":28,"props":399,"children":400},{},[401],{"type":32,"value":402},"问题不在功能数量，而在于没有把文档模型、编辑状态和运行时边界独立出来。",{"type":27,"tag":75,"props":404,"children":406},{"id":405},"一份可直接复用的检查清单",[407],{"type":32,"value":405},{"type":27,"tag":40,"props":409,"children":410},{},[411,416,421,426,431],{"type":27,"tag":44,"props":412,"children":413},{},[414],{"type":32,"value":415},"文档模型是否先于画布实现被定义清楚",{"type":27,"tag":44,"props":417,"children":418},{},[419],{"type":32,"value":420},"选区、拖拽、悬停、对齐是否共享统一状态层",{"type":27,"tag":44,"props":422,"children":423},{},[424],{"type":32,"value":425},"撤销重做是否基于可恢复操作而不是粗暴快照",{"type":27,"tag":44,"props":427,"children":428},{},[429],{"type":32,"value":430},"样式系统是否同时支持编辑能力与约束能力",{"type":27,"tag":44,"props":432,"children":433},{},[434],{"type":32,"value":435},"导出与运行时边界是否在编辑器早期就被设计进去",{"type":27,"tag":75,"props":437,"children":439},{"id":438},"总结",[440],{"type":32,"value":438},{"type":27,"tag":28,"props":442,"children":443},{},[444],{"type":32,"value":445},"可视化编辑器真正的核心，不是把组件拖得更顺滑，而是让文档模型、交互状态、样式约束和运行时边界协同工作。只要先把这几个基础面搭稳，编辑器能力才会随着产品发展越来越强，而不是越做越脆。",{"type":27,"tag":28,"props":447,"children":448},{},[449],{"type":32,"value":450},"进一步阅读：",{"type":27,"tag":40,"props":452,"children":453},{},[454,464,473],{"type":27,"tag":44,"props":455,"children":456},{},[457],{"type":27,"tag":458,"props":459,"children":461},"a",{"href":460},"/topics/frontend/low-code-platform-architecture-analysis",[462],{"type":32,"value":463},"低代码平台技术架构解析",{"type":27,"tag":44,"props":465,"children":466},{},[467],{"type":27,"tag":458,"props":468,"children":470},{"href":469},"/topics/frontend/high-performance-editor-guide",[471],{"type":32,"value":472},"构建高性能富文本编辑器",{"type":27,"tag":44,"props":474,"children":475},{},[476],{"type":27,"tag":458,"props":477,"children":479},{"href":478},"/topics/nuxt/nuxt-edge-rendering-practice",[480],{"type":32,"value":481},"Nuxt 边缘渲染实践",{"title":7,"searchDepth":483,"depth":483,"links":484},3,[485,487,488,489,490,491,492,493],{"id":77,"depth":486,"text":80},2,{"id":126,"depth":486,"text":129},{"id":188,"depth":486,"text":191},{"id":255,"depth":486,"text":258},{"id":299,"depth":486,"text":302},{"id":343,"depth":486,"text":346},{"id":405,"depth":486,"text":405},{"id":438,"depth":486,"text":438},"markdown","content:topics:frontend:visual-editor-core-technology-guide.md","content","topics/frontend/visual-editor-core-technology-guide.md","topics/frontend/visual-editor-core-technology-guide","md",[501,835,1147],{"_path":502,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":503,"description":504,"keywords":505,"image":511,"author":512,"date":513,"readingTime":514,"topic":5,"body":515,"_type":494,"_id":832,"_source":496,"_file":833,"_stem":834,"_extension":499},"/topics/frontend/react-hooks-guide","React Hooks 完全指南","全面讲解 React Hooks，包括内置钩子、自定义钩子和最佳实践",[506,507,508,509,510],"React","Hooks","自定义钩子","状态管理","函数组件","/images/topics/react-hooks-guide.jpg","AI Content Team","2025-12-08",23,{"type":24,"children":516,"toc":813},[517,522,527,533,540,553,559,568,574,583,589,595,604,610,619,625,634,640,649,654,660,669,674,687,715,726,754,759],{"type":27,"tag":75,"props":518,"children":520},{"id":519},"react-hooks-完全指南",[521],{"type":32,"value":503},{"type":27,"tag":28,"props":523,"children":524},{},[525],{"type":32,"value":526},"Hooks 改变了 React 的开发方式。本文全面讲解如何使用和创建 Hooks。",{"type":27,"tag":75,"props":528,"children":530},{"id":529},"内置-hooks",[531],{"type":32,"value":532},"内置 Hooks",{"type":27,"tag":534,"props":535,"children":537},"h3",{"id":536},"usestate-状态管理",[538],{"type":32,"value":539},"useState - 状态管理",{"type":27,"tag":541,"props":542,"children":547},"pre",{"className":543,"code":545,"language":546,"meta":7},[544],"language-javascript","import { useState } from 'react'\n\nfunction Counter() {\n  const [count, setCount] = useState(0)\n  const [name, setName] = useState('John')\n  const [user, setUser] = useState({\n    age: 30,\n    email: 'john@example.com',\n  })\n  \n  // 使用函数初始化状态（对于复杂初始值）\n  const [data, setData] = useState(() => {\n    console.log('初始化数据...')\n    return fetchInitialData() // 仅在首次渲染时调用\n  })\n  \n  return (\n    \u003Cdiv>\n      \u003Cp>计数: {count}\u003C/p>\n      \u003Cbutton onClick={() => setCount(count + 1)}>增加\u003C/button>\n      \n      {/* 函数式更新 */}\n      \u003Cbutton onClick={() => setCount(prev => prev + 1)}>\n        函数式增加\n      \u003C/button>\n      \n      {/* 更新对象 */}\n      \u003Cbutton onClick={() => setUser({ ...user, age: user.age + 1 })}>\n        增加年龄\n      \u003C/button>\n    \u003C/div>\n  )\n}\n","javascript",[548],{"type":27,"tag":549,"props":550,"children":551},"code",{"__ignoreMap":7},[552],{"type":32,"value":545},{"type":27,"tag":534,"props":554,"children":556},{"id":555},"useeffect-副作用处理",[557],{"type":32,"value":558},"useEffect - 副作用处理",{"type":27,"tag":541,"props":560,"children":563},{"className":561,"code":562,"language":546,"meta":7},[544],"import { useState, useEffect } from 'react'\n\nfunction DataFetcher() {\n  const [data, setData] = useState(null)\n  const [loading, setLoading] = useState(true)\n  const [error, setError] = useState(null)\n  const [userId, setUserId] = useState(1)\n  \n  // 副作用 - 每次渲染后执行\n  useEffect(() => {\n    console.log('组件已挂载或已更新')\n  })\n  \n  // 挂载时执行一次\n  useEffect(() => {\n    console.log('组件已挂载')\n    \n    return () => {\n      console.log('组件已卸载')\n    }\n  }, [])\n  \n  // 当 userId 改变时执行\n  useEffect(() => {\n    let isMounted = true // 防止内存泄漏\n    \n    const fetchData = async () => {\n      setLoading(true)\n      try {\n        const response = await fetch(\\`/api/users/\\${userId}\\`)\n        const result = await response.json()\n        \n        if (isMounted) {\n          setData(result)\n        }\n      } catch (err) {\n        if (isMounted) {\n          setError(err)\n        }\n      } finally {\n        if (isMounted) {\n          setLoading(false)\n        }\n      }\n    }\n    \n    fetchData()\n    \n    // 清理函数\n    return () => {\n      isMounted = false\n    }\n  }, [userId])\n  \n  if (loading) return \u003Cp>加载中...\u003C/p>\n  if (error) return \u003Cp>错误: {error.message}\u003C/p>\n  \n  return \u003Cdiv>{data && JSON.stringify(data)}\u003C/div>\n}\n",[564],{"type":27,"tag":549,"props":565,"children":566},{"__ignoreMap":7},[567],{"type":32,"value":562},{"type":27,"tag":534,"props":569,"children":571},{"id":570},"usecontext-跨组件通信",[572],{"type":32,"value":573},"useContext - 跨组件通信",{"type":27,"tag":541,"props":575,"children":578},{"className":576,"code":577,"language":546,"meta":7},[544],"import { createContext, useContext, useState } from 'react'\n\n// 创建上下文\nconst ThemeContext = createContext()\n\n// 提供者组件\nfunction ThemeProvider({ children }) {\n  const [theme, setTheme] = useState('light')\n  \n  const toggleTheme = () => {\n    setTheme(prev => prev === 'light' ? 'dark' : 'light')\n  }\n  \n  const value = { theme, toggleTheme }\n  \n  return (\n    \u003CThemeContext.Provider value={value}>\n      {children}\n    \u003C/ThemeContext.Provider>\n  )\n}\n\n// 使用 Hook\nfunction useTheme() {\n  const context = useContext(ThemeContext)\n  \n  if (!context) {\n    throw new Error('useTheme 必须在 ThemeProvider 内使用')\n  }\n  \n  return context\n}\n\n// 组件使用\nfunction App() {\n  const { theme, toggleTheme } = useTheme()\n  \n  return (\n    \u003Cdiv style={{\n      background: theme === 'light' ? '#fff' : '#333',\n      color: theme === 'light' ? '#000' : '#fff',\n    }}>\n      \u003Cp>当前主题: {theme}\u003C/p>\n      \u003Cbutton onClick={toggleTheme}>切换主题\u003C/button>\n    \u003C/div>\n  )\n}\n\n// 使用\nexport default function Root() {\n  return (\n    \u003CThemeProvider>\n      \u003CApp />\n    \u003C/ThemeProvider>\n  )\n}\n",[579],{"type":27,"tag":549,"props":580,"children":581},{"__ignoreMap":7},[582],{"type":32,"value":577},{"type":27,"tag":75,"props":584,"children":586},{"id":585},"自定义-hooks",[587],{"type":32,"value":588},"自定义 Hooks",{"type":27,"tag":534,"props":590,"children":592},{"id":591},"uselocalstorage",[593],{"type":32,"value":594},"useLocalStorage",{"type":27,"tag":541,"props":596,"children":599},{"className":597,"code":598,"language":546,"meta":7},[544],"import { useState, useEffect } from 'react'\n\nfunction useLocalStorage(key, initialValue) {\n  // 从本地存储获取初始值\n  const [storedValue, setStoredValue] = useState(() => {\n    try {\n      const item = window.localStorage.getItem(key)\n      return item ? JSON.parse(item) : initialValue\n    } catch (error) {\n      console.error(error)\n      return initialValue\n    }\n  })\n  \n  // 当值改变时更新本地存储\n  const setValue = (value) => {\n    try {\n      const valueToStore = value instanceof Function ? value(storedValue) : value\n      setStoredValue(valueToStore)\n      window.localStorage.setItem(key, JSON.stringify(valueToStore))\n    } catch (error) {\n      console.error(error)\n    }\n  }\n  \n  return [storedValue, setValue]\n}\n\n// 使用\nfunction App() {\n  const [name, setName] = useLocalStorage('name', 'Guest')\n  \n  return (\n    \u003Cdiv>\n      \u003Cp>姓名: {name}\u003C/p>\n      \u003Cinput\n        value={name}\n        onChange={(e) => setName(e.target.value)}\n      />\n    \u003C/div>\n  )\n}\n",[600],{"type":27,"tag":549,"props":601,"children":602},{"__ignoreMap":7},[603],{"type":32,"value":598},{"type":27,"tag":534,"props":605,"children":607},{"id":606},"useasync-异步操作",[608],{"type":32,"value":609},"useAsync - 异步操作",{"type":27,"tag":541,"props":611,"children":614},{"className":612,"code":613,"language":546,"meta":7},[544],"import { useState, useEffect, useRef } from 'react'\n\nfunction useAsync(asyncFunction, immediate = true) {\n  const [status, setStatus] = useState('idle')\n  const [value, setValue] = useState(null)\n  const [error, setError] = useState(null)\n  \n  // 使用 ref 来防止无限循环\n  const executeRef = useRef(null)\n  \n  const execute = useRef(async () => {\n    setStatus('pending')\n    setValue(null)\n    setError(null)\n    \n    try {\n      const response = await asyncFunction()\n      setValue(response)\n      setStatus('success')\n      return response\n    } catch (error) {\n      setError(error)\n      setStatus('error')\n    }\n  })\n  \n  executeRef.current = execute.current\n  \n  useEffect(() => {\n    if (!immediate) return\n    \n    executeRef.current()\n  }, [immediate])\n  \n  return { execute: executeRef.current, status, value, error }\n}\n\n// 使用\nfunction UserProfile({ userId }) {\n  const { execute, status, value: user, error } = useAsync(\n    () => fetch(\\`/api/users/\\${userId}\\`).then(r => r.json()),\n    true\n  )\n  \n  if (status === 'pending') return \u003Cp>加载中...\u003C/p>\n  if (status === 'error') return \u003Cp>错误: {error?.message}\u003C/p>\n  if (status === 'success') return \u003Cp>用户: {user?.name}\u003C/p>\n  \n  return null\n}\n",[615],{"type":27,"tag":549,"props":616,"children":617},{"__ignoreMap":7},[618],{"type":32,"value":613},{"type":27,"tag":534,"props":620,"children":622},{"id":621},"usefetch-数据获取",[623],{"type":32,"value":624},"useFetch - 数据获取",{"type":27,"tag":541,"props":626,"children":629},{"className":627,"code":628,"language":546,"meta":7},[544],"import { useState, useEffect } from 'react'\n\nfunction useFetch(url, options = {}) {\n  const [data, setData] = useState(null)\n  const [loading, setLoading] = useState(true)\n  const [error, setError] = useState(null)\n  \n  useEffect(() => {\n    let isMounted = true\n    \n    const fetchData = async () => {\n      try {\n        const response = await fetch(url, {\n          method: 'GET',\n          ...options,\n        })\n        \n        if (!response.ok) {\n          throw new Error(\\`HTTP error! status: \\${response.status}\\`)\n        }\n        \n        const result = await response.json()\n        \n        if (isMounted) {\n          setData(result)\n          setError(null)\n        }\n      } catch (err) {\n        if (isMounted) {\n          setError(err)\n          setData(null)\n        }\n      } finally {\n        if (isMounted) {\n          setLoading(false)\n        }\n      }\n    }\n    \n    fetchData()\n    \n    return () => {\n      isMounted = false\n    }\n  }, [url, options])\n  \n  const refetch = async () => {\n    setLoading(true)\n    try {\n      const response = await fetch(url, options)\n      const result = await response.json()\n      setData(result)\n    } catch (err) {\n      setError(err)\n    } finally {\n      setLoading(false)\n    }\n  }\n  \n  return { data, loading, error, refetch }\n}\n\n// 使用\nfunction UserList() {\n  const { data: users, loading, error, refetch } = useFetch('/api/users')\n  \n  if (loading) return \u003Cp>加载中...\u003C/p>\n  if (error) return \u003Cp>错误: {error.message}\u003C/p>\n  \n  return (\n    \u003Cdiv>\n      \u003Cbutton onClick={refetch}>刷新\u003C/button>\n      \u003Cul>\n        {users?.map(user => (\n          \u003Cli key={user.id}>{user.name}\u003C/li>\n        ))}\n      \u003C/ul>\n    \u003C/div>\n  )\n}\n",[630],{"type":27,"tag":549,"props":631,"children":632},{"__ignoreMap":7},[633],{"type":32,"value":628},{"type":27,"tag":534,"props":635,"children":637},{"id":636},"useprevious-保存前一个值",[638],{"type":32,"value":639},"usePrevious - 保存前一个值",{"type":27,"tag":541,"props":641,"children":644},{"className":642,"code":643,"language":546,"meta":7},[544],"import { useEffect, useRef } from 'react'\n\nfunction usePrevious(value) {\n  const ref = useRef()\n  \n  useEffect(() => {\n    ref.current = value\n  }, [value])\n  \n  return ref.current\n}\n\n// 使用\nfunction Counter() {\n  const [count, setCount] = React.useState(0)\n  const prevCount = usePrevious(count)\n  \n  return (\n    \u003Cdiv>\n      \u003Cp>当前: {count}, 前一个: {prevCount}\u003C/p>\n      \u003Cbutton onClick={() => setCount(count + 1)}>增加\u003C/button>\n    \u003C/div>\n  )\n}\n",[645],{"type":27,"tag":549,"props":646,"children":647},{"__ignoreMap":7},[648],{"type":32,"value":643},{"type":27,"tag":75,"props":650,"children":652},{"id":651},"高级模式",[653],{"type":32,"value":651},{"type":27,"tag":534,"props":655,"children":657},{"id":656},"usereducer-复杂状态管理",[658],{"type":32,"value":659},"useReducer - 复杂状态管理",{"type":27,"tag":541,"props":661,"children":664},{"className":662,"code":663,"language":546,"meta":7},[544],"import { useReducer } from 'react'\n\nconst initialState = {\n  todos: [],\n  filter: 'all',\n  error: null,\n}\n\nfunction todoReducer(state, action) {\n  switch (action.type) {\n    case 'ADD_TODO':\n      return {\n        ...state,\n        todos: [...state.todos, { id: Date.now(), text: action.payload }],\n      }\n    \n    case 'REMOVE_TODO':\n      return {\n        ...state,\n        todos: state.todos.filter(todo => todo.id !== action.payload),\n      }\n    \n    case 'SET_FILTER':\n      return { ...state, filter: action.payload }\n    \n    case 'SET_ERROR':\n      return { ...state, error: action.payload }\n    \n    default:\n      return state\n  }\n}\n\nfunction TodoApp() {\n  const [state, dispatch] = useReducer(todoReducer, initialState)\n  \n  const addTodo = (text) => {\n    dispatch({ type: 'ADD_TODO', payload: text })\n  }\n  \n  const removeTodo = (id) => {\n    dispatch({ type: 'REMOVE_TODO', payload: id })\n  }\n  \n  return (\n    \u003Cdiv>\n      {state.todos.map(todo => (\n        \u003Cdiv key={todo.id}>\n          {todo.text}\n          \u003Cbutton onClick={() => removeTodo(todo.id)}>删除\u003C/button>\n        \u003C/div>\n      ))}\n    \u003C/div>\n  )\n}\n",[665],{"type":27,"tag":549,"props":666,"children":667},{"__ignoreMap":7},[668],{"type":32,"value":663},{"type":27,"tag":75,"props":670,"children":672},{"id":671},"最佳实践",[673],{"type":32,"value":671},{"type":27,"tag":28,"props":675,"children":676},{},[677,679,685],{"type":32,"value":678},"✅ ",{"type":27,"tag":680,"props":681,"children":682},"strong",{},[683],{"type":32,"value":684},"应该做的事",{"type":32,"value":686},":",{"type":27,"tag":40,"props":688,"children":689},{},[690,695,700,705,710],{"type":27,"tag":44,"props":691,"children":692},{},[693],{"type":32,"value":694},"将相关逻辑提取到自定义 Hooks",{"type":27,"tag":44,"props":696,"children":697},{},[698],{"type":32,"value":699},"在 useEffect 的依赖数组中包含所有依赖",{"type":27,"tag":44,"props":701,"children":702},{},[703],{"type":32,"value":704},"使用 useCallback 和 useMemo 优化性能",{"type":27,"tag":44,"props":706,"children":707},{},[708],{"type":32,"value":709},"为自定义 Hooks 编写文档",{"type":27,"tag":44,"props":711,"children":712},{},[713],{"type":32,"value":714},"及时清理副作用",{"type":27,"tag":28,"props":716,"children":717},{},[718,720,725],{"type":32,"value":719},"❌ ",{"type":27,"tag":680,"props":721,"children":722},{},[723],{"type":32,"value":724},"不应该做的事",{"type":32,"value":686},{"type":27,"tag":40,"props":727,"children":728},{},[729,734,739,744,749],{"type":27,"tag":44,"props":730,"children":731},{},[732],{"type":32,"value":733},"在条件或循环中调用 Hooks",{"type":27,"tag":44,"props":735,"children":736},{},[737],{"type":32,"value":738},"在普通函数中调用 Hooks",{"type":27,"tag":44,"props":740,"children":741},{},[742],{"type":32,"value":743},"忘记依赖数组",{"type":27,"tag":44,"props":745,"children":746},{},[747],{"type":32,"value":748},"过度使用 useMemo/useCallback",{"type":27,"tag":44,"props":750,"children":751},{},[752],{"type":32,"value":753},"在 Hooks 中创建过多的闭包",{"type":27,"tag":75,"props":755,"children":757},{"id":756},"检查清单",[758],{"type":32,"value":756},{"type":27,"tag":40,"props":760,"children":763},{"className":761},[762],"contains-task-list",[764,777,786,795,804],{"type":27,"tag":44,"props":765,"children":768},{"className":766},[767],"task-list-item",[769,775],{"type":27,"tag":770,"props":771,"children":774},"input",{"disabled":772,"type":773},true,"checkbox",[],{"type":32,"value":776}," Hooks 调用顺序正确",{"type":27,"tag":44,"props":778,"children":780},{"className":779},[767],[781,784],{"type":27,"tag":770,"props":782,"children":783},{"disabled":772,"type":773},[],{"type":32,"value":785}," 依赖数组完整",{"type":27,"tag":44,"props":787,"children":789},{"className":788},[767],[790,793],{"type":27,"tag":770,"props":791,"children":792},{"disabled":772,"type":773},[],{"type":32,"value":794}," 副作用正确清理",{"type":27,"tag":44,"props":796,"children":798},{"className":797},[767],[799,802],{"type":27,"tag":770,"props":800,"children":801},{"disabled":772,"type":773},[],{"type":32,"value":803}," 性能优化得当",{"type":27,"tag":44,"props":805,"children":807},{"className":806},[767],[808,811],{"type":27,"tag":770,"props":809,"children":810},{"disabled":772,"type":773},[],{"type":32,"value":812}," 代码易于理解和测试",{"title":7,"searchDepth":483,"depth":483,"links":814},[815,816,821,827,830,831],{"id":519,"depth":486,"text":503},{"id":529,"depth":486,"text":532,"children":817},[818,819,820],{"id":536,"depth":483,"text":539},{"id":555,"depth":483,"text":558},{"id":570,"depth":483,"text":573},{"id":585,"depth":486,"text":588,"children":822},[823,824,825,826],{"id":591,"depth":483,"text":594},{"id":606,"depth":483,"text":609},{"id":621,"depth":483,"text":624},{"id":636,"depth":483,"text":639},{"id":651,"depth":486,"text":651,"children":828},[829],{"id":656,"depth":483,"text":659},{"id":671,"depth":486,"text":671},{"id":756,"depth":486,"text":756},"content:topics:frontend:react-hooks-guide.md","topics/frontend/react-hooks-guide.md","topics/frontend/react-hooks-guide",{"_path":836,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":837,"description":838,"keywords":839,"image":845,"author":512,"date":513,"readingTime":846,"topic":5,"body":847,"_type":494,"_id":1144,"_source":496,"_file":1145,"_stem":1146,"_extension":499},"/topics/frontend/vue3-composition-api","Vue 3 Composition API 深度解析","全面讲解 Vue 3 Composition API 的用法、最佳实践和高级模式",[840,841,842,843,844],"Vue 3","Composition API","组合式函数","响应式系统","前端开发","/images/topics/vue3-composition-api.jpg",22,{"type":24,"children":848,"toc":1120},[849,854,859,864,870,879,884,893,897,902,911,916,922,931,936,942,951,956,961,970,975,981,990,994,1003,1031,1040,1068,1072],{"type":27,"tag":75,"props":850,"children":852},{"id":851},"vue-3-composition-api-深度解析",[853],{"type":32,"value":837},{"type":27,"tag":28,"props":855,"children":856},{},[857],{"type":32,"value":858},"Composition API 让 Vue 应用更易于组织和重用逻辑。本文深入讲解这一核心特性。",{"type":27,"tag":75,"props":860,"children":862},{"id":861},"核心概念",[863],{"type":32,"value":861},{"type":27,"tag":534,"props":865,"children":867},{"id":866},"setup-函数",[868],{"type":32,"value":869},"setup 函数",{"type":27,"tag":541,"props":871,"children":874},{"className":872,"code":873,"language":546,"meta":7},[544],"import { ref, computed, watch } from 'vue'\n\nexport default {\n  props: ['initialCount'],\n  emits: ['count-changed'],\n  \n  setup(props, { emit, slots, expose }) {\n    // 创建响应式状态\n    const count = ref(props.initialCount)\n    const doubled = computed(() => count.value * 2)\n    \n    // 监听状态变化\n    watch(count, (newVal, oldVal) => {\n      console.log(`Count changed from ${oldVal} to ${newVal}`)\n      emit('count-changed', newVal)\n    })\n    \n    // 定义方法\n    const increment = () => count.value++\n    const decrement = () => count.value--\n    \n    // 返回模板需要的内容\n    return {\n      count,\n      doubled,\n      increment,\n      decrement,\n    }\n  },\n}\n",[875],{"type":27,"tag":549,"props":876,"children":877},{"__ignoreMap":7},[878],{"type":32,"value":873},{"type":27,"tag":534,"props":880,"children":882},{"id":881},"响应式基础",[883],{"type":32,"value":881},{"type":27,"tag":541,"props":885,"children":888},{"className":886,"code":887,"language":546,"meta":7},[544],"import { ref, reactive, readonly, isRef } from 'vue'\n\n// ref - 用于基本类型\nconst count = ref(0)\nconsole.log(count.value) // 0\ncount.value++\n\n// reactive - 用于对象\nconst state = reactive({\n  name: 'John',\n  age: 30,\n  address: {\n    city: 'Beijing',\n  },\n})\n\nstate.name = 'Jane' // 自动更新，无需 .value\n\n// readonly - 创建只读副本\nconst original = reactive({ count: 0 })\nconst copy = readonly(original)\n// copy.count++ // 错误：不能修改\n\n// isRef 检查\nconsole.log(isRef(count)) // true\nconsole.log(isRef(state)) // false\n",[889],{"type":27,"tag":549,"props":890,"children":891},{"__ignoreMap":7},[892],{"type":32,"value":887},{"type":27,"tag":75,"props":894,"children":895},{"id":842},[896],{"type":32,"value":842},{"type":27,"tag":534,"props":898,"children":900},{"id":899},"创建可重用逻辑",[901],{"type":32,"value":899},{"type":27,"tag":541,"props":903,"children":906},{"className":904,"code":905,"language":546,"meta":7},[544],"// useCounter.js - 组合式函数\nimport { ref, computed } from 'vue'\n\nexport function useCounter(initialValue = 0) {\n  const count = ref(initialValue)\n  const doubled = computed(() => count.value * 2)\n  \n  const increment = () => count.value++\n  const decrement = () => count.value--\n  const reset = () => count.value = initialValue\n  \n  return {\n    count,\n    doubled,\n    increment,\n    decrement,\n    reset,\n  }\n}\n\n// useFetch.js - 数据获取组合式函数\nimport { ref, onMounted } from 'vue'\n\nexport function useFetch(url) {\n  const data = ref(null)\n  const loading = ref(false)\n  const error = ref(null)\n  \n  const fetch = async () => {\n    loading.value = true\n    error.value = null\n    \n    try {\n      const response = await fetch(url)\n      data.value = await response.json()\n    } catch (e) {\n      error.value = e\n    } finally {\n      loading.value = false\n    }\n  }\n  \n  onMounted(fetch)\n  \n  return {\n    data,\n    loading,\n    error,\n    refetch: fetch,\n  }\n}\n\n// 使用\nexport default {\n  setup() {\n    const { count, doubled, increment } = useCounter(10)\n    const { data, loading, refetch } = useFetch('/api/data')\n    \n    return {\n      count,\n      doubled,\n      increment,\n      data,\n      loading,\n      refetch,\n    }\n  },\n}\n",[907],{"type":27,"tag":549,"props":908,"children":909},{"__ignoreMap":7},[910],{"type":32,"value":905},{"type":27,"tag":75,"props":912,"children":914},{"id":913},"生命周期钩子",[915],{"type":32,"value":913},{"type":27,"tag":534,"props":917,"children":919},{"id":918},"composition-api-中的生命周期",[920],{"type":32,"value":921},"Composition API 中的生命周期",{"type":27,"tag":541,"props":923,"children":926},{"className":924,"code":925,"language":546,"meta":7},[544],"import {\n  onBeforeMount,\n  onMounted,\n  onBeforeUpdate,\n  onUpdated,\n  onBeforeUnmount,\n  onUnmounted,\n  onErrorCaptured,\n} from 'vue'\n\nexport default {\n  setup() {\n    onBeforeMount(() => {\n      console.log('组件挂载前')\n    })\n    \n    onMounted(() => {\n      console.log('组件已挂载')\n      // 初始化事件监听器、定时器等\n    })\n    \n    onBeforeUpdate(() => {\n      console.log('组件更新前')\n    })\n    \n    onUpdated(() => {\n      console.log('组件已更新')\n    })\n    \n    onBeforeUnmount(() => {\n      console.log('组件卸载前')\n    })\n    \n    onUnmounted(() => {\n      console.log('组件已卸载')\n      // 清理事件监听器、定时器等\n    })\n    \n    onErrorCaptured((err, instance, info) => {\n      console.log('捕获错误:', err)\n      return false // 返回 false 阻止错误传播\n    })\n    \n    return {}\n  },\n}\n",[927],{"type":27,"tag":549,"props":928,"children":929},{"__ignoreMap":7},[930],{"type":32,"value":925},{"type":27,"tag":75,"props":932,"children":934},{"id":933},"模板引用",[935],{"type":32,"value":933},{"type":27,"tag":534,"props":937,"children":939},{"id":938},"访问-dom-元素",[940],{"type":32,"value":941},"访问 DOM 元素",{"type":27,"tag":541,"props":943,"children":946},{"className":944,"code":945,"language":546,"meta":7},[544],"import { ref, onMounted } from 'vue'\n\nexport default {\n  setup() {\n    const inputRef = ref(null)\n    const listRef = ref(null)\n    const dynamicRef = ref(null)\n    \n    onMounted(() => {\n      // 访问 DOM 元素\n      inputRef.value?.focus()\n      console.log(listRef.value?.offsetHeight)\n    })\n    \n    // 函数式引用\n    const assignRef = el => {\n      if (el) {\n        console.log('元素已赋值', el)\n      } else {\n        console.log('元素已移除')\n      }\n    }\n    \n    return {\n      inputRef,\n      listRef,\n      dynamicRef,\n      assignRef,\n    }\n  },\n  \n  template: \\`\n    \u003Cdiv>\n      \u003Cinput ref=\"inputRef\" />\n      \u003Cul ref=\"listRef\">\n        \u003Cli v-for=\"item in items\" :key=\"item\">{{ item }}\u003C/li>\n      \u003C/ul>\n      \u003Cdiv :ref=\"assignRef\">\u003C/div>\n    \u003C/div>\n  \\`,\n}\n",[947],{"type":27,"tag":549,"props":948,"children":949},{"__ignoreMap":7},[950],{"type":32,"value":945},{"type":27,"tag":75,"props":952,"children":954},{"id":953},"依赖注入",[955],{"type":32,"value":953},{"type":27,"tag":534,"props":957,"children":959},{"id":958},"跨组件共享数据",[960],{"type":32,"value":958},{"type":27,"tag":541,"props":962,"children":965},{"className":963,"code":964,"language":546,"meta":7},[544],"import { provide, inject, ref, readonly } from 'vue'\n\n// 父组件\nexport default {\n  setup() {\n    const theme = ref('light')\n    const user = ref({ name: 'John', role: 'admin' })\n    \n    // 提供数据给子组件\n    provide('theme', readonly(theme))\n    provide('updateTheme', (newTheme) => {\n      theme.value = newTheme\n    })\n    \n    // 使用 Symbol 作为 key 避免命名冲突\n    const userKey = Symbol()\n    provide(userKey, readonly(user))\n    \n    return {\n      theme,\n      updateTheme: (newTheme) => {\n        theme.value = newTheme\n      },\n    }\n  },\n}\n\n// 子组件\nexport default {\n  setup() {\n    // 注入数据\n    const theme = inject('theme')\n    const updateTheme = inject('updateTheme')\n    const user = inject(Symbol.for('user'))\n    \n    // 带默认值的注入\n    const config = inject('config', {\n      apiUrl: 'http://localhost:3000',\n    })\n    \n    return {\n      theme,\n      updateTheme,\n      user,\n      config,\n    }\n  },\n}\n",[966],{"type":27,"tag":549,"props":967,"children":968},{"__ignoreMap":7},[969],{"type":32,"value":964},{"type":27,"tag":75,"props":971,"children":973},{"id":972},"高级状态管理",[974],{"type":32,"value":972},{"type":27,"tag":534,"props":976,"children":978},{"id":977},"创建小型-store",[979],{"type":32,"value":980},"创建小型 store",{"type":27,"tag":541,"props":982,"children":985},{"className":983,"code":984,"language":546,"meta":7},[544],"import { reactive, readonly, computed } from 'vue'\n\n// store.js - 不依赖 Pinia 的简单 store\nexport function createStore() {\n  const state = reactive({\n    items: [],\n    filter: 'all',\n    sortBy: 'date',\n  })\n  \n  const filteredItems = computed(() => {\n    let result = state.items\n    \n    if (state.filter !== 'all') {\n      result = result.filter(item => item.status === state.filter)\n    }\n    \n    if (state.sortBy === 'date') {\n      result.sort((a, b) => new Date(b.date) - new Date(a.date))\n    } else if (state.sortBy === 'name') {\n      result.sort((a, b) => a.name.localeCompare(b.name))\n    }\n    \n    return result\n  })\n  \n  const actions = {\n    addItem(item) {\n      state.items.push({ ...item, id: Date.now() })\n    },\n    \n    removeItem(id) {\n      state.items = state.items.filter(item => item.id !== id)\n    },\n    \n    updateItem(id, updates) {\n      const item = state.items.find(item => item.id === id)\n      if (item) {\n        Object.assign(item, updates)\n      }\n    },\n    \n    setFilter(filter) {\n      state.filter = filter\n    },\n    \n    setSortBy(sortBy) {\n      state.sortBy = sortBy\n    },\n  }\n  \n  return {\n    state: readonly(state),\n    filteredItems,\n    ...actions,\n  }\n}\n\n// 使用\nexport default {\n  setup() {\n    const store = createStore()\n    \n    const handleAdd = (item) => {\n      store.addItem(item)\n    }\n    \n    return {\n      items: store.filteredItems,\n      addItem: handleAdd,\n      setFilter: store.setFilter,\n    }\n  },\n}\n",[986],{"type":27,"tag":549,"props":987,"children":988},{"__ignoreMap":7},[989],{"type":32,"value":984},{"type":27,"tag":75,"props":991,"children":992},{"id":671},[993],{"type":32,"value":671},{"type":27,"tag":28,"props":995,"children":996},{},[997,998,1002],{"type":32,"value":678},{"type":27,"tag":680,"props":999,"children":1000},{},[1001],{"type":32,"value":684},{"type":32,"value":686},{"type":27,"tag":40,"props":1004,"children":1005},{},[1006,1011,1016,1021,1026],{"type":27,"tag":44,"props":1007,"children":1008},{},[1009],{"type":32,"value":1010},"将相关逻辑组织在一起",{"type":27,"tag":44,"props":1012,"children":1013},{},[1014],{"type":32,"value":1015},"创建可重用的组合式函数",{"type":27,"tag":44,"props":1017,"children":1018},{},[1019],{"type":32,"value":1020},"使用 TypeScript 获得更好的类型检查",{"type":27,"tag":44,"props":1022,"children":1023},{},[1024],{"type":32,"value":1025},"合理使用计算属性和监听器",{"type":27,"tag":44,"props":1027,"children":1028},{},[1029],{"type":32,"value":1030},"及时清理事件监听器和定时器",{"type":27,"tag":28,"props":1032,"children":1033},{},[1034,1035,1039],{"type":32,"value":719},{"type":27,"tag":680,"props":1036,"children":1037},{},[1038],{"type":32,"value":724},{"type":32,"value":686},{"type":27,"tag":40,"props":1041,"children":1042},{},[1043,1048,1053,1058,1063],{"type":27,"tag":44,"props":1044,"children":1045},{},[1046],{"type":32,"value":1047},"在 setup 中执行副作用操作（除了生命周期钩子）",{"type":27,"tag":44,"props":1049,"children":1050},{},[1051],{"type":32,"value":1052},"过度使用计算属性",{"type":27,"tag":44,"props":1054,"children":1055},{},[1056],{"type":32,"value":1057},"忘记清理 watch 监听器",{"type":27,"tag":44,"props":1059,"children":1060},{},[1061],{"type":32,"value":1062},"在 reactive 对象中存储引用类型时不谨慎",{"type":27,"tag":44,"props":1064,"children":1065},{},[1066],{"type":32,"value":1067},"过度复杂化组合式函数",{"type":27,"tag":75,"props":1069,"children":1070},{"id":756},[1071],{"type":32,"value":756},{"type":27,"tag":40,"props":1073,"children":1075},{"className":1074},[762],[1076,1085,1094,1103,1112],{"type":27,"tag":44,"props":1077,"children":1079},{"className":1078},[767],[1080,1083],{"type":27,"tag":770,"props":1081,"children":1082},{"disabled":772,"type":773},[],{"type":32,"value":1084}," 正确使用 ref 和 reactive",{"type":27,"tag":44,"props":1086,"children":1088},{"className":1087},[767],[1089,1092],{"type":27,"tag":770,"props":1090,"children":1091},{"disabled":772,"type":773},[],{"type":32,"value":1093}," 生命周期钩子正确",{"type":27,"tag":44,"props":1095,"children":1097},{"className":1096},[767],[1098,1101],{"type":27,"tag":770,"props":1099,"children":1100},{"disabled":772,"type":773},[],{"type":32,"value":1102}," 模板引用工作正常",{"type":27,"tag":44,"props":1104,"children":1106},{"className":1105},[767],[1107,1110],{"type":27,"tag":770,"props":1108,"children":1109},{"disabled":772,"type":773},[],{"type":32,"value":1111}," 组合式函数可重用",{"type":27,"tag":44,"props":1113,"children":1115},{"className":1114},[767],[1116,1119],{"type":27,"tag":770,"props":1117,"children":1118},{"disabled":772,"type":773},[],{"type":32,"value":803},{"title":7,"searchDepth":483,"depth":483,"links":1121},[1122,1123,1127,1130,1133,1136,1139,1142,1143],{"id":851,"depth":486,"text":837},{"id":861,"depth":486,"text":861,"children":1124},[1125,1126],{"id":866,"depth":483,"text":869},{"id":881,"depth":483,"text":881},{"id":842,"depth":486,"text":842,"children":1128},[1129],{"id":899,"depth":483,"text":899},{"id":913,"depth":486,"text":913,"children":1131},[1132],{"id":918,"depth":483,"text":921},{"id":933,"depth":486,"text":933,"children":1134},[1135],{"id":938,"depth":483,"text":941},{"id":953,"depth":486,"text":953,"children":1137},[1138],{"id":958,"depth":483,"text":958},{"id":972,"depth":486,"text":972,"children":1140},[1141],{"id":977,"depth":483,"text":980},{"id":671,"depth":486,"text":671},{"id":756,"depth":486,"text":756},"content:topics:frontend:vue3-composition-api.md","topics/frontend/vue3-composition-api.md","topics/frontend/vue3-composition-api",{"_path":1148,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1149,"description":1150,"date":1151,"topic":5,"author":11,"tags":1152,"image":1158,"featured":772,"readingTime":1159,"body":1160,"_type":494,"_id":2422,"_source":496,"_file":2423,"_stem":2424,"_extension":499},"/topics/frontend/rspack-performance-practice","Rspack 构建性能实战","从 Rspack 的架构设计与编译管线出发，系统对比 Webpack/Vite 并给出 Rspack 在大型项目中的迁移路径、性能调优策略与生产级可观测方案。","2026-01-20",[1153,1154,1155,1156,1157],"Rspack","构建工具","性能优化","Webpack","前端工程化","/images/topics/rspack.jpg",25,{"type":24,"children":1161,"toc":2389},[1162,1167,1179,1184,1202,1214,1219,1242,1246,1252,1257,1263,1296,1302,1320,1323,1329,1335,1340,1353,1359,1364,1377,1383,1401,1406,1409,1415,1420,1561,1566,1589,1592,1598,1604,1609,1614,1682,1695,1701,1709,1722,1730,1743,1751,1764,1770,1788,1791,1797,1803,1808,1821,1827,1832,1843,1849,1854,1872,1877,1905,1908,1914,1919,1930,1935,1953,1958,1976,1979,1985,1990,2008,2013,2036,2041,2059,2062,2068,2074,2079,2097,2103,2121,2127,2145,2148,2154,2269,2274,2292,2295,2301,2359,2362,2366,2371],{"type":27,"tag":75,"props":1163,"children":1165},{"id":1164},"rspack-构建性能实战",[1166],{"type":32,"value":1149},{"type":27,"tag":28,"props":1168,"children":1169},{},[1170,1172,1177],{"type":32,"value":1171},"Rspack 不是\"又一个构建工具\"，而是字节跳动在处理",{"type":27,"tag":680,"props":1173,"children":1174},{},[1175],{"type":32,"value":1176},"超大规模前端项目",{"type":32,"value":1178},"时，对 Webpack 生态的 Rust 重写与工程化沉淀。",{"type":27,"tag":28,"props":1180,"children":1181},{},[1182],{"type":32,"value":1183},"它要解决的核心问题是：",{"type":27,"tag":40,"props":1185,"children":1186},{},[1187,1192,1197],{"type":27,"tag":44,"props":1188,"children":1189},{},[1190],{"type":32,"value":1191},"Webpack 的构建速度在大型 monorepo 下（10k+ 模块）已成为开发体验瓶颈",{"type":27,"tag":44,"props":1193,"children":1194},{},[1195],{"type":32,"value":1196},"但你又无法抛弃 Webpack 的插件生态与配置范式",{"type":27,"tag":44,"props":1198,"children":1199},{},[1200],{"type":32,"value":1201},"Vite 虽然快，但在某些场景（大型遗留项目、特定插件依赖）迁移成本高",{"type":27,"tag":28,"props":1203,"children":1204},{},[1205,1207,1212],{"type":32,"value":1206},"Rspack 的定位是：",{"type":27,"tag":680,"props":1208,"children":1209},{},[1210],{"type":32,"value":1211},"Webpack 兼容 API + Rust 性能 + 生产级稳定性",{"type":32,"value":1213},"。",{"type":27,"tag":28,"props":1215,"children":1216},{},[1217],{"type":32,"value":1218},"这篇文章不讲\"Hello World\"，而是按\"你要在生产上稳定用 Rspack\"的标准，给出：",{"type":27,"tag":40,"props":1220,"children":1221},{},[1222,1227,1232,1237],{"type":27,"tag":44,"props":1223,"children":1224},{},[1225],{"type":32,"value":1226},"性能收益的真实量化方法",{"type":27,"tag":44,"props":1228,"children":1229},{},[1230],{"type":32,"value":1231},"迁移路径与兼容性边界",{"type":27,"tag":44,"props":1233,"children":1234},{},[1235],{"type":32,"value":1236},"优化策略（缓存、并行、Tree Shaking）",{"type":27,"tag":44,"props":1238,"children":1239},{},[1240],{"type":32,"value":1241},"监控与排障（为什么变慢、为什么产物变大）",{"type":27,"tag":1243,"props":1244,"children":1245},"hr",{},[],{"type":27,"tag":75,"props":1247,"children":1249},{"id":1248},"_1-先回答什么项目值得迁移-rspack",[1250],{"type":32,"value":1251},"1. 先回答：什么项目值得迁移 Rspack？",{"type":27,"tag":28,"props":1253,"children":1254},{},[1255],{"type":32,"value":1256},"不是所有项目都需要 Rspack。",{"type":27,"tag":534,"props":1258,"children":1260},{"id":1259},"_11-高收益场景",[1261],{"type":32,"value":1262},"1.1 高收益场景",{"type":27,"tag":40,"props":1264,"children":1265},{},[1266,1276,1286],{"type":27,"tag":44,"props":1267,"children":1268},{},[1269,1274],{"type":27,"tag":680,"props":1270,"children":1271},{},[1272],{"type":32,"value":1273},"大型 monorepo",{"type":32,"value":1275},"（5k+ 模块，构建时间 > 2 分钟）",{"type":27,"tag":44,"props":1277,"children":1278},{},[1279,1284],{"type":27,"tag":680,"props":1280,"children":1281},{},[1282],{"type":32,"value":1283},"频繁开发迭代",{"type":32,"value":1285},"（HMR 延迟影响体验）",{"type":27,"tag":44,"props":1287,"children":1288},{},[1289,1294],{"type":27,"tag":680,"props":1290,"children":1291},{},[1292],{"type":32,"value":1293},"CI 构建成本高",{"type":32,"value":1295},"（每次 PR 构建超 10 分钟）",{"type":27,"tag":534,"props":1297,"children":1299},{"id":1298},"_12-收益不明显的场景",[1300],{"type":32,"value":1301},"1.2 收益不明显的场景",{"type":27,"tag":40,"props":1303,"children":1304},{},[1305,1310,1315],{"type":27,"tag":44,"props":1306,"children":1307},{},[1308],{"type":32,"value":1309},"小型项目（\u003C 1k 模块）",{"type":27,"tag":44,"props":1311,"children":1312},{},[1313],{"type":32,"value":1314},"已经用 Vite 且体验良好",{"type":27,"tag":44,"props":1316,"children":1317},{},[1318],{"type":32,"value":1319},"高度定制的 Webpack 插件（迁移成本 > 性能收益）",{"type":27,"tag":1243,"props":1321,"children":1322},{},[],{"type":27,"tag":75,"props":1324,"children":1326},{"id":1325},"_2-rspack-的架构为什么能快",[1327],{"type":32,"value":1328},"2. Rspack 的架构：为什么能快？",{"type":27,"tag":534,"props":1330,"children":1332},{"id":1331},"_21-rust-并行编译",[1333],{"type":32,"value":1334},"2.1 Rust 并行编译",{"type":27,"tag":28,"props":1336,"children":1337},{},[1338],{"type":32,"value":1339},"Webpack 是单线程 JavaScript，Rspack 是多线程 Rust。",{"type":27,"tag":40,"props":1341,"children":1342},{},[1343,1348],{"type":27,"tag":44,"props":1344,"children":1345},{},[1346],{"type":32,"value":1347},"模块解析、编译、优化可并行",{"type":27,"tag":44,"props":1349,"children":1350},{},[1351],{"type":32,"value":1352},"I/O 密集型任务（读文件、写产物）异步化",{"type":27,"tag":534,"props":1354,"children":1356},{"id":1355},"_22-更激进的缓存策略",[1357],{"type":32,"value":1358},"2.2 更激进的缓存策略",{"type":27,"tag":28,"props":1360,"children":1361},{},[1362],{"type":32,"value":1363},"Rspack 内置持久化缓存：",{"type":27,"tag":40,"props":1365,"children":1366},{},[1367,1372],{"type":27,"tag":44,"props":1368,"children":1369},{},[1370],{"type":32,"value":1371},"模块级别缓存（类似 Webpack 5 的 cache.type: 'filesystem'）",{"type":27,"tag":44,"props":1373,"children":1374},{},[1375],{"type":32,"value":1376},"但实现更激进：对未变化模块跳过编译",{"type":27,"tag":534,"props":1378,"children":1380},{"id":1379},"_23-内置常用功能减少插件开销",[1381],{"type":32,"value":1382},"2.3 内置常用功能（减少插件开销）",{"type":27,"tag":40,"props":1384,"children":1385},{},[1386,1391,1396],{"type":27,"tag":44,"props":1387,"children":1388},{},[1389],{"type":32,"value":1390},"SWC 替代 Babel（内置 TS/JSX/装饰器）",{"type":27,"tag":44,"props":1392,"children":1393},{},[1394],{"type":32,"value":1395},"CSS Modules、PostCSS 内置",{"type":27,"tag":44,"props":1397,"children":1398},{},[1399],{"type":32,"value":1400},"Tree Shaking 内置",{"type":27,"tag":28,"props":1402,"children":1403},{},[1404],{"type":32,"value":1405},"这让 Rspack 在相同功能下比 Webpack + 插件链路更快。",{"type":27,"tag":1243,"props":1407,"children":1408},{},[],{"type":27,"tag":75,"props":1410,"children":1412},{"id":1411},"_3-性能对比真实场景的量化",[1413],{"type":32,"value":1414},"3. 性能对比：真实场景的量化",{"type":27,"tag":28,"props":1416,"children":1417},{},[1418],{"type":32,"value":1419},"我们用一个典型中型项目（3k 模块，React + TS + CSS Modules）做对比：",{"type":27,"tag":1421,"props":1422,"children":1423},"table",{},[1424,1452],{"type":27,"tag":1425,"props":1426,"children":1427},"thead",{},[1428],{"type":27,"tag":1429,"props":1430,"children":1431},"tr",{},[1432,1438,1443,1447],{"type":27,"tag":1433,"props":1434,"children":1435},"th",{},[1436],{"type":32,"value":1437},"指标",{"type":27,"tag":1433,"props":1439,"children":1440},{},[1441],{"type":32,"value":1442},"Webpack 5",{"type":27,"tag":1433,"props":1444,"children":1445},{},[1446],{"type":32,"value":1153},{"type":27,"tag":1433,"props":1448,"children":1449},{},[1450],{"type":32,"value":1451},"提升",{"type":27,"tag":1453,"props":1454,"children":1455},"tbody",{},[1456,1483,1509,1535],{"type":27,"tag":1429,"props":1457,"children":1458},{},[1459,1465,1470,1475],{"type":27,"tag":1460,"props":1461,"children":1462},"td",{},[1463],{"type":32,"value":1464},"冷启动",{"type":27,"tag":1460,"props":1466,"children":1467},{},[1468],{"type":32,"value":1469},"42s",{"type":27,"tag":1460,"props":1471,"children":1472},{},[1473],{"type":32,"value":1474},"8s",{"type":27,"tag":1460,"props":1476,"children":1477},{},[1478],{"type":27,"tag":680,"props":1479,"children":1480},{},[1481],{"type":32,"value":1482},"5.2x",{"type":27,"tag":1429,"props":1484,"children":1485},{},[1486,1491,1496,1501],{"type":27,"tag":1460,"props":1487,"children":1488},{},[1489],{"type":32,"value":1490},"HMR（热更新）",{"type":27,"tag":1460,"props":1492,"children":1493},{},[1494],{"type":32,"value":1495},"1.2s",{"type":27,"tag":1460,"props":1497,"children":1498},{},[1499],{"type":32,"value":1500},"0.15s",{"type":27,"tag":1460,"props":1502,"children":1503},{},[1504],{"type":27,"tag":680,"props":1505,"children":1506},{},[1507],{"type":32,"value":1508},"8x",{"type":27,"tag":1429,"props":1510,"children":1511},{},[1512,1517,1522,1527],{"type":27,"tag":1460,"props":1513,"children":1514},{},[1515],{"type":32,"value":1516},"生产构建",{"type":27,"tag":1460,"props":1518,"children":1519},{},[1520],{"type":32,"value":1521},"125s",{"type":27,"tag":1460,"props":1523,"children":1524},{},[1525],{"type":32,"value":1526},"28s",{"type":27,"tag":1460,"props":1528,"children":1529},{},[1530],{"type":27,"tag":680,"props":1531,"children":1532},{},[1533],{"type":32,"value":1534},"4.5x",{"type":27,"tag":1429,"props":1536,"children":1537},{},[1538,1543,1548,1553],{"type":27,"tag":1460,"props":1539,"children":1540},{},[1541],{"type":32,"value":1542},"内存峰值",{"type":27,"tag":1460,"props":1544,"children":1545},{},[1546],{"type":32,"value":1547},"1.8GB",{"type":27,"tag":1460,"props":1549,"children":1550},{},[1551],{"type":32,"value":1552},"0.9GB",{"type":27,"tag":1460,"props":1554,"children":1555},{},[1556],{"type":27,"tag":680,"props":1557,"children":1558},{},[1559],{"type":32,"value":1560},"2x",{"type":27,"tag":28,"props":1562,"children":1563},{},[1564],{"type":32,"value":1565},"关键收益：",{"type":27,"tag":40,"props":1567,"children":1568},{},[1569,1579],{"type":27,"tag":44,"props":1570,"children":1571},{},[1572,1577],{"type":27,"tag":680,"props":1573,"children":1574},{},[1575],{"type":32,"value":1576},"开发体验质变",{"type":32,"value":1578},"（HMR \u003C 200ms）",{"type":27,"tag":44,"props":1580,"children":1581},{},[1582,1587],{"type":27,"tag":680,"props":1583,"children":1584},{},[1585],{"type":32,"value":1586},"CI 成本减半",{"type":32,"value":1588},"（构建时间直接影响 Runner 费用）",{"type":27,"tag":1243,"props":1590,"children":1591},{},[],{"type":27,"tag":75,"props":1593,"children":1595},{"id":1594},"_4-迁移路径从-webpack-到-rspack",[1596],{"type":32,"value":1597},"4. 迁移路径：从 Webpack 到 Rspack",{"type":27,"tag":534,"props":1599,"children":1601},{"id":1600},"_41-最小迁移保守策略",[1602],{"type":32,"value":1603},"4.1 最小迁移（保守策略）",{"type":27,"tag":28,"props":1605,"children":1606},{},[1607],{"type":32,"value":1608},"目标：用最小改动换取性能收益。",{"type":27,"tag":28,"props":1610,"children":1611},{},[1612],{"type":32,"value":1613},"步骤：",{"type":27,"tag":1615,"props":1616,"children":1617},"ol",{},[1618,1637,1656,1677],{"type":27,"tag":44,"props":1619,"children":1620},{},[1621,1623,1629,1631],{"type":32,"value":1622},"安装 ",{"type":27,"tag":549,"props":1624,"children":1626},{"className":1625},[],[1627],{"type":32,"value":1628},"@rspack/cli",{"type":32,"value":1630}," 与 ",{"type":27,"tag":549,"props":1632,"children":1634},{"className":1633},[],[1635],{"type":32,"value":1636},"@rspack/core",{"type":27,"tag":44,"props":1638,"children":1639},{},[1640,1642,1648,1650],{"type":32,"value":1641},"把 ",{"type":27,"tag":549,"props":1643,"children":1645},{"className":1644},[],[1646],{"type":32,"value":1647},"webpack.config.js",{"type":32,"value":1649}," 改为 ",{"type":27,"tag":549,"props":1651,"children":1653},{"className":1652},[],[1654],{"type":32,"value":1655},"rspack.config.js",{"type":27,"tag":44,"props":1657,"children":1658},{},[1659,1661,1667,1669,1675],{"type":32,"value":1660},"替换构建命令（",{"type":27,"tag":549,"props":1662,"children":1664},{"className":1663},[],[1665],{"type":32,"value":1666},"rspack build",{"type":32,"value":1668}," / ",{"type":27,"tag":549,"props":1670,"children":1672},{"className":1671},[],[1673],{"type":32,"value":1674},"rspack dev",{"type":32,"value":1676},"）",{"type":27,"tag":44,"props":1678,"children":1679},{},[1680],{"type":32,"value":1681},"运行并修复兼容性问题",{"type":27,"tag":28,"props":1683,"children":1684},{},[1685,1687,1693],{"type":32,"value":1686},"预计迁移成本：1",{"type":27,"tag":1688,"props":1689,"children":1690},"del",{},[1691],{"type":32,"value":1692},"2 天（小型项目）/ 1",{"type":32,"value":1694},"2 周（大型项目）",{"type":27,"tag":534,"props":1696,"children":1698},{"id":1697},"_42-兼容性边界哪些需要调整",[1699],{"type":32,"value":1700},"4.2 兼容性边界：哪些需要调整",{"type":27,"tag":28,"props":1702,"children":1703},{},[1704],{"type":27,"tag":680,"props":1705,"children":1706},{},[1707],{"type":32,"value":1708},"插件兼容",{"type":27,"tag":40,"props":1710,"children":1711},{},[1712,1717],{"type":27,"tag":44,"props":1713,"children":1714},{},[1715],{"type":32,"value":1716},"Rspack 支持大部分 Webpack 插件（API 兼容）",{"type":27,"tag":44,"props":1718,"children":1719},{},[1720],{"type":32,"value":1721},"但少数复杂插件（例如深度依赖 Webpack 内部 API）需要适配",{"type":27,"tag":28,"props":1723,"children":1724},{},[1725],{"type":27,"tag":680,"props":1726,"children":1727},{},[1728],{"type":32,"value":1729},"Loader 兼容",{"type":27,"tag":40,"props":1731,"children":1732},{},[1733,1738],{"type":27,"tag":44,"props":1734,"children":1735},{},[1736],{"type":32,"value":1737},"常用 loader（babel-loader、css-loader、postcss-loader）兼容",{"type":27,"tag":44,"props":1739,"children":1740},{},[1741],{"type":32,"value":1742},"部分自定义 loader 需要测试",{"type":27,"tag":28,"props":1744,"children":1745},{},[1746],{"type":27,"tag":680,"props":1747,"children":1748},{},[1749],{"type":32,"value":1750},"配置差异",{"type":27,"tag":40,"props":1752,"children":1753},{},[1754,1759],{"type":27,"tag":44,"props":1755,"children":1756},{},[1757],{"type":32,"value":1758},"resolve、output、optimization 等配置与 Webpack 高度一致",{"type":27,"tag":44,"props":1760,"children":1761},{},[1762],{"type":32,"value":1763},"少数高级配置需要查文档",{"type":27,"tag":534,"props":1765,"children":1767},{"id":1766},"_43-推荐的迁移节奏",[1768],{"type":32,"value":1769},"4.3 推荐的迁移节奏",{"type":27,"tag":40,"props":1771,"children":1772},{},[1773,1778,1783],{"type":27,"tag":44,"props":1774,"children":1775},{},[1776],{"type":32,"value":1777},"Week 1：本地开发环境先行",{"type":27,"tag":44,"props":1779,"children":1780},{},[1781],{"type":32,"value":1782},"Week 2：CI 构建切换（并保留 Webpack 作为 fallback）",{"type":27,"tag":44,"props":1784,"children":1785},{},[1786],{"type":32,"value":1787},"Week 3~4：生产构建切换并观测",{"type":27,"tag":1243,"props":1789,"children":1790},{},[],{"type":27,"tag":75,"props":1792,"children":1794},{"id":1793},"_5-性能调优让-rspack-更快",[1795],{"type":32,"value":1796},"5. 性能调优：让 Rspack 更快",{"type":27,"tag":534,"props":1798,"children":1800},{"id":1799},"_51-缓存策略",[1801],{"type":32,"value":1802},"5.1 缓存策略",{"type":27,"tag":28,"props":1804,"children":1805},{},[1806],{"type":32,"value":1807},"默认缓存已经很激进，但你可以：",{"type":27,"tag":40,"props":1809,"children":1810},{},[1811,1816],{"type":27,"tag":44,"props":1812,"children":1813},{},[1814],{"type":32,"value":1815},"显式配置缓存目录（例如挂载 SSD）",{"type":27,"tag":44,"props":1817,"children":1818},{},[1819],{"type":32,"value":1820},"在 CI 上持久化缓存（例如用 actions/cache）",{"type":27,"tag":534,"props":1822,"children":1824},{"id":1823},"_52-并行度调优",[1825],{"type":32,"value":1826},"5.2 并行度调优",{"type":27,"tag":28,"props":1828,"children":1829},{},[1830],{"type":32,"value":1831},"Rspack 默认会用所有 CPU 核心，但在容器环境（例如 CI）可能需要限制：",{"type":27,"tag":541,"props":1833,"children":1838},{"className":1834,"code":1836,"language":1837,"meta":7},[1835],"language-js","module.exports = {\n  experiments: {\n    rspackFuture: {\n      disableTransformByDefault: true, // 减少不必要转换\n    },\n  },\n}\n","js",[1839],{"type":27,"tag":549,"props":1840,"children":1841},{"__ignoreMap":7},[1842],{"type":32,"value":1836},{"type":27,"tag":534,"props":1844,"children":1846},{"id":1845},"_53-tree-shaking-与-dead-code-elimination",[1847],{"type":32,"value":1848},"5.3 Tree Shaking 与 Dead Code Elimination",{"type":27,"tag":28,"props":1850,"children":1851},{},[1852],{"type":32,"value":1853},"Rspack 内置 Tree Shaking，但效果取决于：",{"type":27,"tag":40,"props":1855,"children":1856},{},[1857,1862,1867],{"type":27,"tag":44,"props":1858,"children":1859},{},[1860],{"type":32,"value":1861},"是否使用 ESM（而非 CommonJS）",{"type":27,"tag":44,"props":1863,"children":1864},{},[1865],{"type":32,"value":1866},"副作用标记（sideEffects: false）",{"type":27,"tag":44,"props":1868,"children":1869},{},[1870],{"type":32,"value":1871},"动态 import 的拆分策略",{"type":27,"tag":28,"props":1873,"children":1874},{},[1875],{"type":32,"value":1876},"建议：",{"type":27,"tag":40,"props":1878,"children":1879},{},[1880,1893],{"type":27,"tag":44,"props":1881,"children":1882},{},[1883,1885,1891],{"type":32,"value":1884},"对第三方库检查 ",{"type":27,"tag":549,"props":1886,"children":1888},{"className":1887},[],[1889],{"type":32,"value":1890},"sideEffects",{"type":32,"value":1892}," 配置",{"type":27,"tag":44,"props":1894,"children":1895},{},[1896,1898,1904],{"type":32,"value":1897},"避免\"全量引入后 tree shake\"（例如 ",{"type":27,"tag":549,"props":1899,"children":1901},{"className":1900},[],[1902],{"type":32,"value":1903},"import * from 'lodash'",{"type":32,"value":1676},{"type":27,"tag":1243,"props":1906,"children":1907},{},[],{"type":27,"tag":75,"props":1909,"children":1911},{"id":1910},"_6-产物分析与优化",[1912],{"type":32,"value":1913},"6. 产物分析与优化",{"type":27,"tag":28,"props":1915,"children":1916},{},[1917],{"type":32,"value":1918},"Rspack 提供内置分析工具：",{"type":27,"tag":541,"props":1920,"children":1925},{"className":1921,"code":1923,"language":1924,"meta":7},[1922],"language-bash","rspack build --analyze\n","bash",[1926],{"type":27,"tag":549,"props":1927,"children":1928},{"__ignoreMap":7},[1929],{"type":32,"value":1923},{"type":27,"tag":28,"props":1931,"children":1932},{},[1933],{"type":32,"value":1934},"关键指标：",{"type":27,"tag":40,"props":1936,"children":1937},{},[1938,1943,1948],{"type":27,"tag":44,"props":1939,"children":1940},{},[1941],{"type":32,"value":1942},"各 chunk 体积分布",{"type":27,"tag":44,"props":1944,"children":1945},{},[1946],{"type":32,"value":1947},"重复依赖（例如多个版本的 lodash）",{"type":27,"tag":44,"props":1949,"children":1950},{},[1951],{"type":32,"value":1952},"未被 tree shake 的代码",{"type":27,"tag":28,"props":1954,"children":1955},{},[1956],{"type":32,"value":1957},"优化策略：",{"type":27,"tag":40,"props":1959,"children":1960},{},[1961,1966,1971],{"type":27,"tag":44,"props":1962,"children":1963},{},[1964],{"type":32,"value":1965},"拆分 vendor chunk（按更新频率）",{"type":27,"tag":44,"props":1967,"children":1968},{},[1969],{"type":32,"value":1970},"对大型库按需引入（例如 antd/lodash-es）",{"type":27,"tag":44,"props":1972,"children":1973},{},[1974],{"type":32,"value":1975},"检查动态 import 的粒度",{"type":27,"tag":1243,"props":1977,"children":1978},{},[],{"type":27,"tag":75,"props":1980,"children":1982},{"id":1981},"_7-生产可观测性让构建可量化",[1983],{"type":32,"value":1984},"7. 生产可观测性：让构建可量化",{"type":27,"tag":28,"props":1986,"children":1987},{},[1988],{"type":32,"value":1989},"在 CI/CD 里，你需要能回答：",{"type":27,"tag":40,"props":1991,"children":1992},{},[1993,1998,2003],{"type":27,"tag":44,"props":1994,"children":1995},{},[1996],{"type":32,"value":1997},"这次构建为什么变慢？",{"type":27,"tag":44,"props":1999,"children":2000},{},[2001],{"type":32,"value":2002},"产物为什么变大？",{"type":27,"tag":44,"props":2004,"children":2005},{},[2006],{"type":32,"value":2007},"哪个模块耗时最多？",{"type":27,"tag":28,"props":2009,"children":2010},{},[2011],{"type":32,"value":2012},"建议在 CI 里记录：",{"type":27,"tag":40,"props":2014,"children":2015},{},[2016,2021,2026,2031],{"type":27,"tag":44,"props":2017,"children":2018},{},[2019],{"type":32,"value":2020},"构建总耗时",{"type":27,"tag":44,"props":2022,"children":2023},{},[2024],{"type":32,"value":2025},"各阶段耗时（resolve、compile、optimize、emit）",{"type":27,"tag":44,"props":2027,"children":2028},{},[2029],{"type":32,"value":2030},"产物体积（按 chunk）",{"type":27,"tag":44,"props":2032,"children":2033},{},[2034],{"type":32,"value":2035},"缓存命中率",{"type":27,"tag":28,"props":2037,"children":2038},{},[2039],{"type":32,"value":2040},"落地方式：",{"type":27,"tag":40,"props":2042,"children":2043},{},[2044,2049,2054],{"type":27,"tag":44,"props":2045,"children":2046},{},[2047],{"type":32,"value":2048},"用 Rspack 的 stats 输出",{"type":27,"tag":44,"props":2050,"children":2051},{},[2052],{"type":32,"value":2053},"在 CI 日志里保留关键指标",{"type":27,"tag":44,"props":2055,"children":2056},{},[2057],{"type":32,"value":2058},"对产物体积做 baseline 对比（变化 > 5% 报警）",{"type":27,"tag":1243,"props":2060,"children":2061},{},[],{"type":27,"tag":75,"props":2063,"children":2065},{"id":2064},"_8-常见问题排查",[2066],{"type":32,"value":2067},"8. 常见问题排查",{"type":27,"tag":534,"props":2069,"children":2071},{"id":2070},"_81-迁移后变慢了",[2072],{"type":32,"value":2073},"8.1 \"迁移后变慢了\"",{"type":27,"tag":28,"props":2075,"children":2076},{},[2077],{"type":32,"value":2078},"排查顺序：",{"type":27,"tag":40,"props":2080,"children":2081},{},[2082,2087,2092],{"type":27,"tag":44,"props":2083,"children":2084},{},[2085],{"type":32,"value":2086},"缓存是否生效（首次构建慢正常）",{"type":27,"tag":44,"props":2088,"children":2089},{},[2090],{"type":32,"value":2091},"是否有 loader 拖慢（例如未优化的自定义 loader）",{"type":27,"tag":44,"props":2093,"children":2094},{},[2095],{"type":32,"value":2096},"并行度是否受限（例如 CI 限制 CPU）",{"type":27,"tag":534,"props":2098,"children":2100},{"id":2099},"_82-产物体积变大了",[2101],{"type":32,"value":2102},"8.2 \"产物体积变大了\"",{"type":27,"tag":40,"props":2104,"children":2105},{},[2106,2111,2116],{"type":27,"tag":44,"props":2107,"children":2108},{},[2109],{"type":32,"value":2110},"检查 Tree Shaking 是否生效",{"type":27,"tag":44,"props":2112,"children":2113},{},[2114],{"type":32,"value":2115},"检查是否引入了更多 polyfill",{"type":27,"tag":44,"props":2117,"children":2118},{},[2119],{"type":32,"value":2120},"对比 chunk 分布（用 analyze）",{"type":27,"tag":534,"props":2122,"children":2124},{"id":2123},"_83-某些模块编译失败",[2125],{"type":32,"value":2126},"8.3 \"某些模块编译失败\"",{"type":27,"tag":40,"props":2128,"children":2129},{},[2130,2135,2140],{"type":27,"tag":44,"props":2131,"children":2132},{},[2133],{"type":32,"value":2134},"检查是否依赖 Webpack 特定 API",{"type":27,"tag":44,"props":2136,"children":2137},{},[2138],{"type":32,"value":2139},"查看 Rspack 官方兼容性列表",{"type":27,"tag":44,"props":2141,"children":2142},{},[2143],{"type":32,"value":2144},"在 GitHub Issues 搜索类似问题",{"type":27,"tag":1243,"props":2146,"children":2147},{},[],{"type":27,"tag":75,"props":2149,"children":2151},{"id":2150},"_9-rspack-vs-vite什么时候选哪个",[2152],{"type":32,"value":2153},"9. Rspack vs Vite：什么时候选哪个？",{"type":27,"tag":1421,"props":2155,"children":2156},{},[2157,2177],{"type":27,"tag":1425,"props":2158,"children":2159},{},[2160],{"type":27,"tag":1429,"props":2161,"children":2162},{},[2163,2168,2172],{"type":27,"tag":1433,"props":2164,"children":2165},{},[2166],{"type":32,"value":2167},"维度",{"type":27,"tag":1433,"props":2169,"children":2170},{},[2171],{"type":32,"value":1153},{"type":27,"tag":1433,"props":2173,"children":2174},{},[2175],{"type":32,"value":2176},"Vite",{"type":27,"tag":1453,"props":2178,"children":2179},{},[2180,2198,2215,2233,2251],{"type":27,"tag":1429,"props":2181,"children":2182},{},[2183,2188,2193],{"type":27,"tag":1460,"props":2184,"children":2185},{},[2186],{"type":32,"value":2187},"开发速度",{"type":27,"tag":1460,"props":2189,"children":2190},{},[2191],{"type":32,"value":2192},"极快（Rust 编译）",{"type":27,"tag":1460,"props":2194,"children":2195},{},[2196],{"type":32,"value":2197},"极快（ESM 直连）",{"type":27,"tag":1429,"props":2199,"children":2200},{},[2201,2205,2210],{"type":27,"tag":1460,"props":2202,"children":2203},{},[2204],{"type":32,"value":1516},{"type":27,"tag":1460,"props":2206,"children":2207},{},[2208],{"type":32,"value":2209},"快（全量编译优化）",{"type":27,"tag":1460,"props":2211,"children":2212},{},[2213],{"type":32,"value":2214},"快（Rollup）",{"type":27,"tag":1429,"props":2216,"children":2217},{},[2218,2223,2228],{"type":27,"tag":1460,"props":2219,"children":2220},{},[2221],{"type":32,"value":2222},"Webpack 兼容",{"type":27,"tag":1460,"props":2224,"children":2225},{},[2226],{"type":32,"value":2227},"高",{"type":27,"tag":1460,"props":2229,"children":2230},{},[2231],{"type":32,"value":2232},"低",{"type":27,"tag":1429,"props":2234,"children":2235},{},[2236,2241,2246],{"type":27,"tag":1460,"props":2237,"children":2238},{},[2239],{"type":32,"value":2240},"插件生态",{"type":27,"tag":1460,"props":2242,"children":2243},{},[2244],{"type":32,"value":2245},"Webpack 生态",{"type":27,"tag":1460,"props":2247,"children":2248},{},[2249],{"type":32,"value":2250},"Rollup/Vite 生态",{"type":27,"tag":1429,"props":2252,"children":2253},{},[2254,2259,2264],{"type":27,"tag":1460,"props":2255,"children":2256},{},[2257],{"type":32,"value":2258},"适用项目",{"type":27,"tag":1460,"props":2260,"children":2261},{},[2262],{"type":32,"value":2263},"Webpack 迁移、大型 monorepo",{"type":27,"tag":1460,"props":2265,"children":2266},{},[2267],{"type":32,"value":2268},"新项目、中小型",{"type":27,"tag":28,"props":2270,"children":2271},{},[2272],{"type":32,"value":2273},"选择建议：",{"type":27,"tag":40,"props":2275,"children":2276},{},[2277,2282,2287],{"type":27,"tag":44,"props":2278,"children":2279},{},[2280],{"type":32,"value":2281},"新项目：优先 Vite",{"type":27,"tag":44,"props":2283,"children":2284},{},[2285],{"type":32,"value":2286},"Webpack 遗留项目：Rspack",{"type":27,"tag":44,"props":2288,"children":2289},{},[2290],{"type":32,"value":2291},"大型 monorepo + Webpack 依赖：Rspack",{"type":27,"tag":1243,"props":2293,"children":2294},{},[],{"type":27,"tag":75,"props":2296,"children":2298},{"id":2297},"_10-上线检查清单",[2299],{"type":32,"value":2300},"10. 上线检查清单",{"type":27,"tag":40,"props":2302,"children":2304},{"className":2303},[762],[2305,2314,2323,2332,2341,2350],{"type":27,"tag":44,"props":2306,"children":2308},{"className":2307},[767],[2309,2312],{"type":27,"tag":770,"props":2310,"children":2311},{"disabled":772,"type":773},[],{"type":32,"value":2313}," 本地开发环境已验证（HMR/热更新正常）",{"type":27,"tag":44,"props":2315,"children":2317},{"className":2316},[767],[2318,2321],{"type":27,"tag":770,"props":2319,"children":2320},{"disabled":772,"type":773},[],{"type":32,"value":2322}," CI 构建已切换并观测 3 天以上",{"type":27,"tag":44,"props":2324,"children":2326},{"className":2325},[767],[2327,2330],{"type":27,"tag":770,"props":2328,"children":2329},{"disabled":772,"type":773},[],{"type":32,"value":2331}," 产物体积对比无异常（baseline ± 5%）",{"type":27,"tag":44,"props":2333,"children":2335},{"className":2334},[767],[2336,2339],{"type":27,"tag":770,"props":2337,"children":2338},{"disabled":772,"type":773},[],{"type":32,"value":2340}," 关键页面功能回归测试通过",{"type":27,"tag":44,"props":2342,"children":2344},{"className":2343},[767],[2345,2348],{"type":27,"tag":770,"props":2346,"children":2347},{"disabled":772,"type":773},[],{"type":32,"value":2349}," 有构建耗时与缓存命中率监控",{"type":27,"tag":44,"props":2351,"children":2353},{"className":2352},[767],[2354,2357],{"type":27,"tag":770,"props":2355,"children":2356},{"disabled":772,"type":773},[],{"type":32,"value":2358}," 有回滚方案（保留 Webpack 配置）",{"type":27,"tag":1243,"props":2360,"children":2361},{},[],{"type":27,"tag":75,"props":2363,"children":2364},{"id":438},[2365],{"type":32,"value":438},{"type":27,"tag":28,"props":2367,"children":2368},{},[2369],{"type":32,"value":2370},"Rspack 的核心价值是：",{"type":27,"tag":40,"props":2372,"children":2373},{},[2374,2379,2384],{"type":27,"tag":44,"props":2375,"children":2376},{},[2377],{"type":32,"value":2378},"在 Webpack 生态下获得接近 Vite 的速度",{"type":27,"tag":44,"props":2380,"children":2381},{},[2382],{"type":32,"value":2383},"对大型项目构建成本与开发体验的显著改善",{"type":27,"tag":44,"props":2385,"children":2386},{},[2387],{"type":32,"value":2388},"生产级稳定性（字节跳动内部大规模验证）",{"title":7,"searchDepth":483,"depth":483,"links":2390},[2391,2392,2396,2401,2402,2407,2412,2413,2414,2419,2420,2421],{"id":1164,"depth":486,"text":1149},{"id":1248,"depth":486,"text":1251,"children":2393},[2394,2395],{"id":1259,"depth":483,"text":1262},{"id":1298,"depth":483,"text":1301},{"id":1325,"depth":486,"text":1328,"children":2397},[2398,2399,2400],{"id":1331,"depth":483,"text":1334},{"id":1355,"depth":483,"text":1358},{"id":1379,"depth":483,"text":1382},{"id":1411,"depth":486,"text":1414},{"id":1594,"depth":486,"text":1597,"children":2403},[2404,2405,2406],{"id":1600,"depth":483,"text":1603},{"id":1697,"depth":483,"text":1700},{"id":1766,"depth":483,"text":1769},{"id":1793,"depth":486,"text":1796,"children":2408},[2409,2410,2411],{"id":1799,"depth":483,"text":1802},{"id":1823,"depth":483,"text":1826},{"id":1845,"depth":483,"text":1848},{"id":1910,"depth":486,"text":1913},{"id":1981,"depth":486,"text":1984},{"id":2064,"depth":486,"text":2067,"children":2415},[2416,2417,2418],{"id":2070,"depth":483,"text":2073},{"id":2099,"depth":483,"text":2102},{"id":2123,"depth":483,"text":2126},{"id":2150,"depth":486,"text":2153},{"id":2297,"depth":486,"text":2300},{"id":438,"depth":486,"text":438},"content:topics:frontend:rspack-performance-practice.md","topics/frontend/rspack-performance-practice.md","topics/frontend/rspack-performance-practice",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"topic":5,"author":11,"tags":2426,"image":18,"imageQuery":19,"pexelsPhotoId":20,"pexelsUrl":21,"featured":6,"readingTime":22,"body":2427,"_type":494,"_id":495,"_source":496,"_file":497,"_stem":498,"_extension":499},[13,14,15,16,17],{"type":24,"children":2428,"toc":2790},[2429,2433,2437,2460,2464,2468,2472,2476,2480,2499,2503,2507,2511,2530,2534,2549,2553,2557,2561,2576,2580,2603,2607,2611,2615,2619,2638,2642,2646,2650,2654,2673,2677,2681,2685,2700,2704,2708,2723,2727,2731,2754,2758,2762,2766],{"type":27,"tag":28,"props":2430,"children":2431},{},[2432],{"type":32,"value":33},{"type":27,"tag":28,"props":2434,"children":2435},{},[2436],{"type":32,"value":38},{"type":27,"tag":40,"props":2438,"children":2439},{},[2440,2444,2448,2452,2456],{"type":27,"tag":44,"props":2441,"children":2442},{},[2443],{"type":32,"value":48},{"type":27,"tag":44,"props":2445,"children":2446},{},[2447],{"type":32,"value":53},{"type":27,"tag":44,"props":2449,"children":2450},{},[2451],{"type":32,"value":58},{"type":27,"tag":44,"props":2453,"children":2454},{},[2455],{"type":32,"value":63},{"type":27,"tag":44,"props":2457,"children":2458},{},[2459],{"type":32,"value":68},{"type":27,"tag":28,"props":2461,"children":2462},{},[2463],{"type":32,"value":73},{"type":27,"tag":75,"props":2465,"children":2466},{"id":77},[2467],{"type":32,"value":80},{"type":27,"tag":28,"props":2469,"children":2470},{},[2471],{"type":32,"value":85},{"type":27,"tag":28,"props":2473,"children":2474},{},[2475],{"type":32,"value":90},{"type":27,"tag":28,"props":2477,"children":2478},{},[2479],{"type":32,"value":95},{"type":27,"tag":40,"props":2481,"children":2482},{},[2483,2487,2491,2495],{"type":27,"tag":44,"props":2484,"children":2485},{},[2486],{"type":32,"value":103},{"type":27,"tag":44,"props":2488,"children":2489},{},[2490],{"type":32,"value":108},{"type":27,"tag":44,"props":2492,"children":2493},{},[2494],{"type":32,"value":113},{"type":27,"tag":44,"props":2496,"children":2497},{},[2498],{"type":32,"value":118},{"type":27,"tag":28,"props":2500,"children":2501},{},[2502],{"type":32,"value":123},{"type":27,"tag":75,"props":2504,"children":2505},{"id":126},[2506],{"type":32,"value":129},{"type":27,"tag":28,"props":2508,"children":2509},{},[2510],{"type":32,"value":134},{"type":27,"tag":40,"props":2512,"children":2513},{},[2514,2518,2522,2526],{"type":27,"tag":44,"props":2515,"children":2516},{},[2517],{"type":32,"value":142},{"type":27,"tag":44,"props":2519,"children":2520},{},[2521],{"type":32,"value":147},{"type":27,"tag":44,"props":2523,"children":2524},{},[2525],{"type":32,"value":152},{"type":27,"tag":44,"props":2527,"children":2528},{},[2529],{"type":32,"value":157},{"type":27,"tag":28,"props":2531,"children":2532},{},[2533],{"type":32,"value":162},{"type":27,"tag":40,"props":2535,"children":2536},{},[2537,2541,2545],{"type":27,"tag":44,"props":2538,"children":2539},{},[2540],{"type":32,"value":170},{"type":27,"tag":44,"props":2542,"children":2543},{},[2544],{"type":32,"value":175},{"type":27,"tag":44,"props":2546,"children":2547},{},[2548],{"type":32,"value":180},{"type":27,"tag":28,"props":2550,"children":2551},{},[2552],{"type":32,"value":185},{"type":27,"tag":75,"props":2554,"children":2555},{"id":188},[2556],{"type":32,"value":191},{"type":27,"tag":28,"props":2558,"children":2559},{},[2560],{"type":32,"value":196},{"type":27,"tag":40,"props":2562,"children":2563},{},[2564,2568,2572],{"type":27,"tag":44,"props":2565,"children":2566},{},[2567],{"type":32,"value":204},{"type":27,"tag":44,"props":2569,"children":2570},{},[2571],{"type":32,"value":209},{"type":27,"tag":44,"props":2573,"children":2574},{},[2575],{"type":32,"value":214},{"type":27,"tag":28,"props":2577,"children":2578},{},[2579],{"type":32,"value":219},{"type":27,"tag":40,"props":2581,"children":2582},{},[2583,2587,2591,2595,2599],{"type":27,"tag":44,"props":2584,"children":2585},{},[2586],{"type":32,"value":227},{"type":27,"tag":44,"props":2588,"children":2589},{},[2590],{"type":32,"value":232},{"type":27,"tag":44,"props":2592,"children":2593},{},[2594],{"type":32,"value":237},{"type":27,"tag":44,"props":2596,"children":2597},{},[2598],{"type":32,"value":242},{"type":27,"tag":44,"props":2600,"children":2601},{},[2602],{"type":32,"value":247},{"type":27,"tag":28,"props":2604,"children":2605},{},[2606],{"type":32,"value":252},{"type":27,"tag":75,"props":2608,"children":2609},{"id":255},[2610],{"type":32,"value":258},{"type":27,"tag":28,"props":2612,"children":2613},{},[2614],{"type":32,"value":263},{"type":27,"tag":28,"props":2616,"children":2617},{},[2618],{"type":32,"value":268},{"type":27,"tag":40,"props":2620,"children":2621},{},[2622,2626,2630,2634],{"type":27,"tag":44,"props":2623,"children":2624},{},[2625],{"type":32,"value":276},{"type":27,"tag":44,"props":2627,"children":2628},{},[2629],{"type":32,"value":281},{"type":27,"tag":44,"props":2631,"children":2632},{},[2633],{"type":32,"value":286},{"type":27,"tag":44,"props":2635,"children":2636},{},[2637],{"type":32,"value":291},{"type":27,"tag":28,"props":2639,"children":2640},{},[2641],{"type":32,"value":296},{"type":27,"tag":75,"props":2643,"children":2644},{"id":299},[2645],{"type":32,"value":302},{"type":27,"tag":28,"props":2647,"children":2648},{},[2649],{"type":32,"value":307},{"type":27,"tag":28,"props":2651,"children":2652},{},[2653],{"type":32,"value":312},{"type":27,"tag":40,"props":2655,"children":2656},{},[2657,2661,2665,2669],{"type":27,"tag":44,"props":2658,"children":2659},{},[2660],{"type":32,"value":320},{"type":27,"tag":44,"props":2662,"children":2663},{},[2664],{"type":32,"value":325},{"type":27,"tag":44,"props":2666,"children":2667},{},[2668],{"type":32,"value":330},{"type":27,"tag":44,"props":2670,"children":2671},{},[2672],{"type":32,"value":335},{"type":27,"tag":28,"props":2674,"children":2675},{},[2676],{"type":32,"value":340},{"type":27,"tag":75,"props":2678,"children":2679},{"id":343},[2680],{"type":32,"value":346},{"type":27,"tag":28,"props":2682,"children":2683},{},[2684],{"type":32,"value":351},{"type":27,"tag":40,"props":2686,"children":2687},{},[2688,2692,2696],{"type":27,"tag":44,"props":2689,"children":2690},{},[2691],{"type":32,"value":359},{"type":27,"tag":44,"props":2693,"children":2694},{},[2695],{"type":32,"value":364},{"type":27,"tag":44,"props":2697,"children":2698},{},[2699],{"type":32,"value":369},{"type":27,"tag":28,"props":2701,"children":2702},{},[2703],{"type":32,"value":374},{"type":27,"tag":28,"props":2705,"children":2706},{},[2707],{"type":32,"value":379},{"type":27,"tag":40,"props":2709,"children":2710},{},[2711,2715,2719],{"type":27,"tag":44,"props":2712,"children":2713},{},[2714],{"type":32,"value":387},{"type":27,"tag":44,"props":2716,"children":2717},{},[2718],{"type":32,"value":392},{"type":27,"tag":44,"props":2720,"children":2721},{},[2722],{"type":32,"value":397},{"type":27,"tag":28,"props":2724,"children":2725},{},[2726],{"type":32,"value":402},{"type":27,"tag":75,"props":2728,"children":2729},{"id":405},[2730],{"type":32,"value":405},{"type":27,"tag":40,"props":2732,"children":2733},{},[2734,2738,2742,2746,2750],{"type":27,"tag":44,"props":2735,"children":2736},{},[2737],{"type":32,"value":415},{"type":27,"tag":44,"props":2739,"children":2740},{},[2741],{"type":32,"value":420},{"type":27,"tag":44,"props":2743,"children":2744},{},[2745],{"type":32,"value":425},{"type":27,"tag":44,"props":2747,"children":2748},{},[2749],{"type":32,"value":430},{"type":27,"tag":44,"props":2751,"children":2752},{},[2753],{"type":32,"value":435},{"type":27,"tag":75,"props":2755,"children":2756},{"id":438},[2757],{"type":32,"value":438},{"type":27,"tag":28,"props":2759,"children":2760},{},[2761],{"type":32,"value":445},{"type":27,"tag":28,"props":2763,"children":2764},{},[2765],{"type":32,"value":450},{"type":27,"tag":40,"props":2767,"children":2768},{},[2769,2776,2783],{"type":27,"tag":44,"props":2770,"children":2771},{},[2772],{"type":27,"tag":458,"props":2773,"children":2774},{"href":460},[2775],{"type":32,"value":463},{"type":27,"tag":44,"props":2777,"children":2778},{},[2779],{"type":27,"tag":458,"props":2780,"children":2781},{"href":469},[2782],{"type":32,"value":472},{"type":27,"tag":44,"props":2784,"children":2785},{},[2786],{"type":27,"tag":458,"props":2787,"children":2788},{"href":478},[2789],{"type":32,"value":481},{"title":7,"searchDepth":483,"depth":483,"links":2791},[2792,2793,2794,2795,2796,2797,2798,2799],{"id":77,"depth":486,"text":80},{"id":126,"depth":486,"text":129},{"id":188,"depth":486,"text":191},{"id":255,"depth":486,"text":258},{"id":299,"depth":486,"text":302},{"id":343,"depth":486,"text":346},{"id":405,"depth":486,"text":405},{"id":438,"depth":486,"text":438},1776916086201]