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