写过前端的人都踩过这个坑——每次等 React 测试跑完,感觉时间都凝固了。今天这件事被 Sentry 一个 HackWeek 用三个 jsdom fix 彻底翻了
写过前端的人都踩过这个坑——每次等 React 测试跑完,感觉时间都凝固了。今天这件事被 Sentry 一个 HackWeek 用三个 jsdom fix 彻底翻了。
Sentry 工程师在年度 HackWeek 里用 GPT-5.6 Sol 跑 profiling,定位到一个大 React 测试文件慢的核心原因:不是测试写得烂,是 jsdom 底层有三个性能漏洞。
第一个坑:label lookup 每次都重扫。 getByRole 查表单 label 的时候,每次都要从 DOM 根节点重新扫所有 label 元素。一次查询 60ms,一个表单页面跑几十次 getByRole,测试时间直接爆了。jsdom 加了 label lookup 缓存之后,同一个 label 的后续查询从 60ms 降到 1ms 以内——91 倍提速。
第二个坑:DOMSelector 的 fast-path 从来没触发。 代码里写了一个”如果 ID 没变就直接用缓存”的优化,但比较逻辑有个 bug,导致 fast-path 永远走不到,全都被踢到慢速 matcher。修了之后,matcher benchmark 快了 89%,getByRole 整体快了 42%。
第三个坑:事件派发每层都重算路径。 dispatchEvent 的时候,每往上一层祖先元素就把整个事件路径重新搜一遍。改成一次算完往下传,事件吞吐量提升 12%~36%。
三个 fix 合在一起,同一个测试文件在 jsdom 30 上比之前快 43%,比 jsdom 26 快 21%。
重要的是:测试代码一行没改。getByRole 写法照旧,userEvent 照旧,只是底层库升级了。不需要重写测试,也不需要换测试结构,升级 jsdom 版本就能吃到提速。
这对用 Vitest + @testing-library/react 的团队尤其有意义。jsdom 这三个 fix 合并之后,实际项目里的表单测试、getByRole 调用密集的场景会直接受益。
下一步:看一下你的 node_modules 里 jsdom 的版本,如果还没到 30,可以先跑一下现有的测试套件看耗时基准,等新版本发布之后直接对比。
评论区
登录后可评论。