为何require('perf_hooks')调用失败?Node.js测试场景报错排查
perf_hooks with sandboxed-module in Node.js v14.8.0 问题背景
你确认perf_hooks是Node.js的核心模块,部分场景下代码能正常运行,但执行npm test时却抛出了ENOENT: no such file or directory, open 'perf_hooks'的错误,报错栈指向了sandboxed-module库的文件读取逻辑。你的lib/profiler.js里用了一段环境判断代码兼容浏览器和Node环境,但测试时触发了Node分支的异常。
报错原因
问题核心出在sandboxed-module的沙箱机制:这个库默认不会把Node.js的核心模块(比如perf_hooks)识别为内置模块,而是会像加载普通第三方模块一样,尝试去文件系统中查找对应的文件。但perf_hooks是Node内置的,不存在于磁盘上,因此抛出了找不到文件的错误。
至于你提到某些场景(比如npm run...)能正常工作,是因为这些场景没有使用sandboxed-module,Node.js会直接加载内置的perf_hooks模块,自然不会出现问题。
解决建议
这里有几个可行的方案,按推荐程度排序:
1. 配置sandboxed-module映射核心模块
在测试代码里使用sandboxed-module.require()时,通过requires选项明确把perf_hooks映射到Node的内置模块。这样沙箱就不会去磁盘找文件,而是直接使用真实的核心模块:
const SandboxedModule = require('sandboxed-module'); // 加载目标模块时,指定perf_hooks的映射关系 const targetModule = SandboxedModule.require('./lib/blabla1.js', { requires: { 'perf_hooks': require('perf_hooks') } });
这是最直接的解决方案,从根源上修复了sandboxed-module对核心模块的错误处理逻辑。
2. 更新sandboxed-module到最新版本
部分旧版本的sandboxed-module可能对Node.js较新的核心模块(perf_hooks在v8.5.0加入)支持不完善。尝试更新到最新版本,看看是否修复了核心模块的识别问题:
npm update sandboxed-module
3. 优化环境判断逻辑(备选)
如果上面的方案暂时无法实施,可以在profiler.js里增加测试环境的判断,强制在测试时直接使用Node的perf_hooks,避免sandboxed-module的错误处理:
const {performance, PerformanceObserver} = (function() { // 测试环境下直接加载内置模块 if (process.env.NODE_ENV === 'test') { return require('perf_hooks'); } try { if (window && typeof window.performance == "undefined") throw new TypeError(); return window; } catch (e) { return require("perf_hooks"); } })();
不过这个方案是绕开问题,不如第一个方案彻底。
内容的提问来源于stack exchange,提问作者4ntoine

