当前位置: 首页 > news >正文

我用一个面板找出构建慢的根因:vite-plugin-inspect 实战诊断

我用一个面板找出构建慢的根因:vite-plugin-inspect 实战诊断

我做了什么

我一直想知道一个问题:Vite 构建慢的时候,到底是哪个插件在拖后腿?

这个问题的难处在于——一个 Vite 项目的vite.config.ts可能挂了 20+ 个插件。手动排查的话,逐个注释插件、重启服务、计时对比,插件之间有依赖关系,注释 A 要连带注释 B,非常折腾。

vite-plugin-inspect 就是为这个问题设计的。我搭建了一个测试仓库,放了 15 个插件(其中 3 个是模拟的"慢插件"),用它完整走了一遍性能诊断流程。

搭建测试场景

为了贴近真实情况,我构造了三种慢场景:

  1. 一个对所有文件做 AST 解析的插件(模拟没有文件过滤的自研插件)
  2. 一个 Vite 生命周期内被重复调用的插件(模拟 HMR 边界重算的副作用)
  3. 一个 resolveId 逻辑有性能问题的插件(模拟 glob 扫描开销)

对应的vite.config.ts大概长这样:

importInspectfrom'vite-plugin-inspect'exportdefaultdefineConfig({plugins:[Inspect(),// 就这一行,零配置slowAstPlugin(),// 模拟:无过滤的 AST 解析repeatedTransform(),// 模拟:重复调用的 transformslowResolveId(),// 模拟:glob 扫描// ... 其余 12 个正常插件]})

仓库里有 50 个模拟模块文件(.tsx/.vue/.mdx),加上 node_modules 里的依赖,总共会被 Vite 处理的模块约 180 个。pnpm dev冷启动稳定在12 秒左右,足够复现慢场景。

诊断三步走

第一步:Plugin Metrics 面板

启动后打开http://localhost:5173/__inspect/,点Plugin Metrics面板。一个柱状图把所有插件的 transform 总耗时从高到低排列出来。

立即锁定了三号嫌疑:

插件transform 总耗时调用次数
slow-ast-plugin5,420ms180
vite:vue2,100ms50
repeated-transform1,840ms380 ⚠️
unplugin-auto-import890ms15
slow-resolve-id760ms45

两条线索:

  • slow-ast-plugin总耗时最高,但调用 180 次——是每个模块都被处理了吗?
  • repeated-transform调用次数 380——180 个模块,怎么多了一倍?

第二步:点进个别模块看 transform 链

Modules面板里搜索一个 .tsx 模块,点进去看它的完整 transform 链路。面板右侧用 CodeMirror 做了 diff 对比——左侧是原始代码,右侧是每一步 transform 后的代码。

这个模块的 transform 链条是这样的:

__load__ (虚拟步骤,原始文件内容) vite:pre-alias (代码无变化 ✓) slow-ast-plugin (代码变化,耗时 420ms) repeated-transform (代码无变化,耗时 180ms) ⚠️ repeated-transform (代码无变化,耗时 175ms) ⚠️ ← 重复调用! vite:vue (无变化) vite:esbuild (最终编译)

repeated-transform对同一个模块被调用了两次,但两次的输出完全一致——diff 面板全绿,一行没变。这解释了为什么它的调用总数是模块数的两倍。

slow-ast-plugin的问题更直接:它对自己不应该处理的文件也过了完整的 AST 解析流程——node_modules里的.js文件、纯 CSS 文件,都触发了解析。

第三步:反向验证

为了确认诊断结果,我给slow-ast-plugin加了文件过滤:

// 修复前plugin.transform=(code,id)=>{returnparseAndTransform(code)// 所有文件都处理}// 修复后plugin.transform=(code,id)=>{constVALID_EXTENSIONS=/\.(tsx|vue|mdx)$/if(!VALID_EXTENSIONS.test(id)||id.includes('node_modules'))returnreturnparseAndTransform(code)}

repeated-transform加了去重:

constseen=newSet<string>()plugin.transform=(code,id)=>{constkey=`${id}::${simpleHash(code)}`if(seen.has(key))returnseen.add(key)// ... 实际逻辑}

重新pnpm dev

指标修复前修复后
冷启动时间12.1s5.3s
slow-ast-plugintransform 总耗时5,420ms1,180ms
repeated-transform调用次数380180
repeated-transformtransform 总耗时1,840ms350ms

改动共约 20 行代码,启动时间砍掉一半。不是因为优化了算法,而是——插件根本不需要处理那么多模块

两个我踩到的 API 细节

整个诊断过程中,vite-plugin-inspect 有两个细节让我更信任它的数据:

1.__load__虚拟步骤

每个模块的 transform 链条第一步都是一个名为__load__的虚拟步骤——它记录的是文件系统的原始内容。有了它,Diff 面板才能展示"原始文件 vs 第一步 transform"的差异。这个步骤不参与耗时统计(start === end),纯粹是为了 Diff 对齐。

如果你自己实现类似的工具,这个"第零步锚点"是个很讨巧的设计——不是 hack,而是数据模型的自然表达。

2. Plugin Metrics 的时间单位

柱状图里的数字是所有模块该插件 transform 的累加耗时,不是"每个模块的平均耗时"。这意味着如果一个插件的 transform 非常快(单次 < 5ms),但被调用了 1000 次——它在柱状图里依然可能很显眼。所以看柱状图时要同时看调用次数,不要被绝对数值误导。

如果手上没有 vite-plugin-inspect

我试着在没有工具的情况下手动排查,结论是:能做,但效率差 10 倍

手动流程大概是:

  1. 注释一半插件 → 看启动时间变没变 → 二分法缩小范围
  2. 给疑似慢插件加console.time/console.timeEnd
  3. 在模块源码里加performance.now()打点

但插件之间有依赖时,二分法会碰到"注释 A 后 B 报错"的问题。而且手动计时不够精确——console.time拿不到"这个模块被哪些插件处理过、每次耗时是多少"的全景。

vite-plugin-inspect 的核心价值是:一次接入,全局透视;不改任何被监控插件的代码;数据粒度到单个模块的单次 transform。这三样合在一起,手动方案做不到。

这个诊断能力的通用性

这套流程不只适用于"找出慢插件"这一个问题。同类场景还包括:

  • 新接手的项目:不了解每个插件做了什么,看 Modules 面板能直观看出模块的转换链路
  • 升级 Vite 大版本后:对比升级前后 Plugin Metrics 的耗时变化,定位兼容性问题
  • 接入新插件后启动变慢:不用猜,面板直接告诉你哪个新插件多了多少耗时
http://www.jsqmd.com/news/1093960/

相关文章:

  • 2026全国AI培训实测封神!5款广东惠州等地AI创业实操教程培训机构口碑广受好评值得选
  • Windows11 向 iPhone 传输文件完整教程
  • 《HarmonyOS技术精讲-ArkWeb》开篇:ArkWeb引擎全景解析
  • 专精特新与高新技术企业为何需要基于容度原理的颠覆性技术?
  • 大湾区首家突破 200 亿估值具身智能公司诞生,自变量超豪华投资阵容曝光
  • 3年以下产品经理需求暴跌42%,但高薪AI岗却激增369%!你还在等什么?
  • 本地文档处理链怎么做轻一点?从 PDF、Markdown 到 JSON 看 ZTools
  • Linux服务器遭勒索病毒入侵应急响应实战:从检测、隔离到系统加固全流程解析
  • 工业自动化检测镜头怎么选?聚焦低畸变、高分辨率与场景适配能力
  • 字节面试题:Agent 的记忆系统怎么设计?短期记忆和长期记忆到底有什么区别?
  • 用 ClaudeAPI 自动生成会议总结、行动项和跟进邮件
  • 如何快速安装和使用AML启动器:XCOM 2模组管理完整指南
  • 【技术解码】AUTOSAR通信栈实战:Dcm模块与诊断传输层(CanTp/DoIP)的协同设计
  • 孩子上课走神坐不住,神经酸能帮忙吗?
  • 旧物回收小程序系统功能介绍
  • Rust的async函数中的集成协作
  • 实战指南:基于STM32G4的互补单极性SPWM生成与全桥逆变控制
  • 小程序商城软件哪个好?从商品管理、支付和复购看选择
  • 全速率全覆盖・高性能 SFP 互连解决方案 —— 佳迅智能 SFP 连接器系列技术解析
  • 葫芦岛全屋定制深度解析:品牌质量缺一不可
  • 迷你世界UGc3.0脚本Wiki[容器模块管理接口]
  • TorchTraceAP:计算机视觉模型性能优化新方案
  • 磁盘I-O瓶颈分析与优化
  • LLM Wiki 完整解析:原理、架构、适用场景与 RAG 对比、组合方案
  • AI时代数据库怎么选?多模融合架构与选型实战指南
  • 2026智能锁选购指南:长租公寓/园区宿舍智能锁从研发到交付全流程深度解析
  • 在线课程制作:教学设计与实践练习的结合
  • 内部钓鱼演练误判为APT攻击的归因分析与治理路径设计
  • GIT 提交记录文件拆分 适用于已推送到远程的提交拆分场景
  • MySQL Binlog 文件分析与同步机制