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