Debugging can save you ton of time. But sometimes to set up debugging configuration correctly can be a nightmare. There are several common gotchas which may trick you.
- Code is in Typescript, but NodeJS in debugger does not understand its syntax.
- You use combination of .ts and .js files with import or export statement
- Debugger does not attach, and breakpoints are ignored
- False positive detection of debug mode (flag
--inspect
or--inspect-brk
did not work for my use case)
NRWL NX is a great tool, but somewhat it complicated debugging of NestJS app. At least for me 🙂 So after a couple of hours of trial and error, this is what finally works for me.
launch.json
Notice that --experimental-modules
is turned on. Also notice usage of pwa-node, and specification of env variables.
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug my NESTJS app",
"type": "pwa-node",
"request": "launch",
"args": ["src/main.ts"], // Path to main entry file
"runtimeArgs": ["--require", "ts-node/register", "--require", "tsconfig-paths/register", "--experimental-modules"],
"cwd": "${workspaceRoot}",
"internalConsoleOptions": "openOnSessionStart",
"env": {
"NODE_ENV": "local",
"NODE_PORT": "8000",
"TS_NODE_PROJECT": "tsconfig.debug.json", // Specify the tsconfig to use. See content of it below.
"IS_DEBUG_MODE": "true" // Custom env variable to detect debug mode
},
"sourceMaps": true,
"console": "internalConsole",
"outputCapture": "std",
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**" // Disable the "could not read source map" error for node_modules
]
}
]
}
tsconfig.debug.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"],
"emitDecoratorMetadata": true,
"target": "es6",
"module": "commonjs",
"importHelpers": false,
"allowJs": true // Fixes combination of .js and .ts files
},
"exclude": ["**/*.spec.ts"],
"include": ["**/*.ts"]
}
Detection of debug mode inside running application
export function isInDebugMode(): boolean {
// can not rely on "--inspect" flag, because that is used when launched via NX. Even in standard launching.
// "--inspect-brk" flag did not work either
// So in normal situation you would use this:
// return /--inspect/.test(process.execArgv.join(' '));
// Workaround using ENV variable
return process.env['IS_DEBUG_MODE'] === 'true';
}
Fix of path to files in debug mode
Normally the asset files would be in workspace/dist/appname/assets
folder. That applies when application is launched normally via nx serve appname
command. But when you launch app in debug mode, then the __dirname
variable may resolve differently, and then the app crashes.
So this is my workaround.
export class SomeFileService {
private readonly encoding = 'utf8';
// Different path in debug mode and standard mode
private readonly pathToFile = isInDebugMode()
? path.resolve('./', 'src/assets/configs/predefined-programs.json')
: path.resolve(__dirname, 'assets/configs/predefined-programs.json');
async readFile(): Promise<T> {
return await readFile(this.pathToFile, this.encoding)
.then((data) => {
const parsedData = JSON.parse(data);
return parsedData;
})
.catch((err) => {
console.error('SomeFileService: Error reading data from ' + this.pathToFile, err);
});
}
}
Happy coding.