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