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