本文适用人群:vscode 用户,并且有 vscode 上 node.js(javascript) debug 经验
最近工作中在写一个 ts 的库项目,但是写的过程中发现 debug 过程不是那么友好。想象一下现在用 vscode 打开一个纯 ts 的代码仓库,针对其中一个模块想用 vscode debugger 进行断点调试,是不是有些无从下手。
假设这里有一个 ts lib
现在想要针对 add 模块进行 debug
首先安装 typescript
ts-node
tsconfig-paths
三个 devDependencies。
- typescript: 不用多说
- ts-node: 基于 register 运行 ts 代码
- tsconfig-paths: ts 项目一般会有一个 tsconfig.json,其中可以配置 path alias。
ts-node
运行时不会去处理文件里写的 path alias(我也不知道为什么),导致报错Cannot find module xxx
,所以需要tsconfig-paths
来帮忙处理
修改 launch.json(无则创建)
在 configurations
里增加一条配置,其中 program
为文件路径,runtimeArgs
为运行 node
时额外添加的参数。比如上述配置在 run
的时候就会执行以下等价命令:
node -r ts-node/register -r tsconfig-paths/register /Users/arichy/Desktop/ts-lib/src/utils/add/index.ts
debug
打开 vscode 的 debug 面板,会出现刚刚添加的名为 add 的一个配置
在目标文件中添加断点,点击运行即可
当然并不推荐这样直接改一个模块,更好的做法是在旁边新建一个专门用于 debug 的文件,引入需要 debug 的模块。然后将上面 launch.json
中对应配置的 program
改为新建的用于 debug 的文件,需要调试的模块则保持原状
这样就完成了针对 ts 模块的 debug
register 简单原理
node -r register.js index.js
-r 选项会在 node 运行 index.js
前引入 register.js
这个文件,结果类似于在 index.js
文件的最开头增加一行代码 require('register.js')
。而在这个 register.js
文件中,可以执行一些副作用代码,比如修改 node require 的行为
举个例子:
const Module = require("module");
const oldLoader = Module._extensions[".js"];
Module._extensions[".js"] = function newLoader(mod, filename) {
const oldCompile = mod._compile;
mod._compile = function newCompile(code, filename) {
const newCode = `console.log('injected by register');${code}`;
return oldCompile.call(mod, newCode, filename);
};
oldLoader(mod, filename);
};
假设这是一个 register.js
文件,其中的副作用代码为重写了 Module._extensions[".js"] 这个方法,导致后面 node 在通过 require
方法加载后缀为.js
的模块时,会调用 newLoader
这个重写的方法。在这个方法里,又重写了一个模块的 _compile
方法。这个方法的第一个参数为模块的代码,第二个参数为模块的路径。所以只需要在这个重写的newCompile
方法里将模块原始代码进行字符串处理(babel 转译、ts 编译等),再交给原生的 _compile
方法处理即可,实现了在 node 运行时,加载一个模块之前先将其编译的目的。
封装成 vscode 插件
一个大型 ts lib 中有非常多的模块,每当需要 debug 其中一个模块时手动去修改 launch.json
会显得很麻烦,所以可以考虑封装成一个 vscode 插件,自动将当前打开窗口对应的文件添加到 launch.json
中
用法:在想要 debug 的窗口文件里按 cmd
+shift
+p
,调出 vscode 的 command 输入框,然后输入 ts-add-to-debug
在二级输入框里输入 configuration 的 name
就会自动在 launch.json(无则创建)里添加一条配置
当然这只是一种最简单的调用形式,也可以通过比如快捷键的形式来调用。
源代码如下:
https://github.com/Arichy/ts-add-to-debuggithub.com