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