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