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