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