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