VSCode中,如何以单元测试为入口调试React源码

问题来源

我将React项目clone到本地,想以单元测试为入口调试源码。

配置launch.json

{
  "version": "0.1.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Jest Entry",
      "program": "${workspaceRoot}/node_modules/.bin/jest",
      "args": [
        "${file}",
        "--config",
        "./scripts/jest/config.source.js",
        "--runInBand"
      ],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "env": {
        "NODE_ENV": "development"
      }
    }
  ]
}

根据以上配置,VSCode会调试当前打开的文件,然后我在测试用例中打断点,这一切都很顺利。
图片描述
但是当我继续把断点打到/packages/react/src/ReactElement.js中时,VSCode无法准确进入断点。
图片描述

个人猜测

Jest是使用Babel来transform源码的(/scripts/jest/preprocessor.js),缺少sourceMap导致VSCode无法把断点映射到源码处。

哪位朋友可以指出我这一调试流程的问题或是提供调试React源码的方法吗?

阅读 5.4k
1 个回答

2023-02-23 更新:

Add option for source maps when running tests #24577 中添加了一个 --sourceMaps 的选项,以方便开启 sourceMaps,其中在 scripts/jest/preprocessor.js#96 的修改会覆盖前面设置的 sourceMaps,导致之前的方法失效

2023-02-23_01-05-48.png

这时候,可以按照这个提交中的方式,使用 scripts/jest/jest-cli.js 并加上参数 --sourceMaps 去使用,或者是通过设置 JEST_ENABLE_SOURCE_MAPS 这个环境变量来设置都可以。

不过这个里有个 bug,在源码中使用了缓存去优化 Jest 性能,但却没有把 JEST_ENABLE_SOURCE_MAPS 这个环境变量加入到生成 CacheKey 的函数参数中,导致如果只有 JEST_ENABLE_SOURCE_MAPS 发生变化,但缓存的 CacheKey 不会发生变化,从而直接使用缓存。也就是第一次运行之后,修改 JEST_ENABLE_SOURCE_MAPS 就没有效果了。这里我提交了一个请求去修复这个 bug

2023-02-23_01-21-21.png

目前有如下两种方式可以正常使用:

  1. 在这个请求合并之后,可以自己手动将process.env.JEST_ENABLE_SOURCE_MAPS || '' 这个代码添加到 scripts/jest/preprocessor.js 对应 131 行的位置。
  2. 或者是可以使用 --no-cache 选项,这样 Jest 就不会去使用缓存了,也可以解决这个问题,虽然这样看起来会牺牲一些性能,但我们是在调试的情况下,所以影响也不会很大。

.vscode/launch.json 配置如下

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Jest Entry",
      "program": "${workspaceRoot}/node_modules/.bin/jest",
      "args": [
        "${file}",
        "--no-cache", // 如果使用第一种方式,就可以不用这个选项了
        "--config",
        "./scripts/jest/config.source.js",
        "--runInBand"
      ],
      "env": {
        "NODE_ENV": "development",
        "JEST_ENABLE_SOURCE_MAPS": "inline",
      }
    }
  ]
}

之前的回答:

你猜得是对的.
你需要在scripts/jest/preprocessor.jsbabel配置中添加sourceMaps: 'both'或者sourceMaps: 'inline'

图片描述

推荐问题