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