5

I'm currently trying to debug a Node JS application written in TypeScript from Visual Studio Code but I have some issues. I have a situation similar to the one described on this question

|-- .settings
|----- launch.json
|-- bin
|----- app.js
|----- app.js.map
|--src
|----- app.ts
|-- tsconfig.json

Then I have the tsconfig.json file:

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "outDir": "bin",
        "rootDir": "src",
        "sourceMap": true
    }
}

The app.ts:

console.log("Hello World!");

The launch.json:

{
    "version": "0.1.0",
    "configurations": [
        {
            "name": "Launch type",
            "type": "node",
            "program": "src/app.ts",
            "stopOnEntry": false,
            "sourceMaps": true,
            "outDir": "bin"
        }
    ]
}

Then I manually compile the project from the command line with

tsc

so I get two files in the bin directory. I set a breakpoint on app.ts and finally run the solution with F5, the application starts and stops at the right line but on the JS file instead the TS one: why???

Am I doing something wrong or trying to achieve the impossible?

Thank you very much for your help! :)

EDIT

I've just shared my project on GitHub in order to make things easier! Take a look if you can! :)

Community
  • 1
  • 1
Brutus
  • 790
  • 3
  • 10
  • 27

4 Answers4

9

It is absolutely possible.

The most likely reason is that the node.js cannot locate corresponding ts files using generated map.js file. You can try to specify "sourceRoot" in tsconfig.json to point to the root of your project:

sourceRoot: "/Users/SomeUser/projects/test"

Personally I prefer to use gulp for this purpose and in my case it would look like this (note - I do not hardcore sourceRoot path here by using node.js global variable '__dirname'):

var ts = require('gulp-typescript');

gulp.task('build.js.dev', function() 
{
    var tsProject = ts.createProject('tsconfig.json');

    var tsResult = tsProject.src()
        .pipe(sourcemaps.init())   
        .pipe(ts(tsProject));  

    return merge([
        //Write definitions 
        //tsResult.dts.pipe(gulp.dest("bin")),
        //Write compiled js
        tsResult.js.pipe(sourcemaps.write("./", { sourceRoot: __dirname })).pipe(gulp.dest("bin"))]);
});

After that examine the generated map.js file. It should contain something like this lines in the beginning:

"sources":["src/app.ts"]

and in the end:

"sourceRoot":"/Users/SomeUser/projects/test"

When combined together they must point to the valid location of your app.ts file. If not - adjust sourceRoot correspondingly.

[EDIT]

Below are the parts of the project identical to yours (without gulp) - that I can debug on my machine.

launch.json:

{
    // Name of configuration; appears in the launch configuration drop down menu.
    "name": "Launch Server",
    // Type of configuration.
    "type": "node",
    // Workspace relative or absolute path to the program.
    "program": "${workspaceRoot}/src/app.ts",
    // Automatically stop program after launch.
    "stopOnEntry": false,
    // Command line arguments passed to the program.
    "args": [],
    // Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.
    "cwd": "${workspaceRoot}",
    // Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH.
    "runtimeExecutable": null,
    // Optional arguments passed to the runtime executable.
    "runtimeArgs": ["--nolazy"],
    // Environment variables passed to the program.
    "env": {
        "NODE_ENV": "development"
    },
    // Use JavaScript source maps (if they exist).
    "sourceMaps": true,
    // If JavaScript source maps are enabled, the generated code is expected in this directory.
    "outDir": "${workspaceRoot}/bin",
    "request": "launch"
}

tsconfig.json:

{ 
    "compilerOptions": { 
        "emitDecoratorMetadata": true, 
        "experimentalDecorators": true,
        "moduleResolution": "node",
        "module": "commonjs", 
        "target": "es6",
        "sourceMap": true,
        "outDir": "bin",
        "declaration": true,
        "noImplicitAny": true
    },
    "exclude": [
        "node_modules",
        "bin",
        ".vscode",
        "typings/browser.d.ts",
        "typings/browser/**"
    ]
} 

And build task in tasks.json:

{
    "version": "0.1.0",

    // The command is tsc. Assumes that tsc has been installed locally using npm install typescript
    "command": "${workspaceRoot}/node_modules/typescript/bin/tsc",

    // The command is a shell script
    "isShellCommand": true,

    // Show the output window only if unrecognized errors occur.
    "showOutput": "silent",

    // args is the HelloWorld program to compile.
    "args": [],

    // use the standard tsc problem matcher to find compile problems
    // in the output.
    "problemMatcher": "$tsc"
}

[EDIT]

I have done the following minor updates to your git repository to be able to debug it locally.

Add package.json in the root folder, and specify there tsc as dependency (I prefer local installations):

{
  "name": "123",
  "namelower": "123",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
  },
  "devDependencies": {
    "typescript": "latest"
  }
}

then go to your git "stackoverflow" root folder and run in command prompt:

npm install

Change in tasks.json "command" line to:

"command": "${workspaceRoot}/node_modules/typescript/bin/tsc",

After doing these steps and building the project I was able to put a breakpoint in app.ts and VSCode stopped on it upon run (F5)

[UPDATE]

Version of tasks.json compatible with windows:

{
    "version": "0.1.0",
    "command": "tsc",

    "showOutput": "always",

    "windows": {
        "command": "node.exe"
    },

    "args": ["${workspaceRoot}\\node_modules\\typescript\\bin\\tsc.js"],

    "problemMatcher": "$tsc"    
}

Hope this helps.

Amid
  • 21,508
  • 5
  • 57
  • 54
  • I tried your suggestion (without Gulp) but it doesn't work, even if in the map file the paths are OK. Are you using the latest Code version (0.10.8)? – Brutus Feb 24 '16 at 17:27
  • Yes - i do. I've included my config section from launch.json that works perfectly for me. – Amid Feb 24 '16 at 17:35
  • Actually mine version is 0.10.9. I was working with VSCode/node.js since quite a while ago - so I do not think its version related. – Amid Feb 24 '16 at 17:42
  • I have added all 'parts' of the test project identical to yours, without using gulp. – Amid Feb 24 '16 at 18:04
  • Thank you very much @Amid, I tried your suggestions but had no luck! :( Now I shared my code on GitHub, could you please try to pull it and check if it works on your machine? Thank you very much for your time, I really appreciate your help. – Brutus Feb 25 '16 at 09:47
  • 1
    Thanks a lot guy! You solved my issue! I followed the instructions in and got the following error at compile time: _"c:\Users\brutus\Desktop\stackoverflow-master/node_modules/typescript/bin/tsc" not recognized as an internal or external command_ Then I reverted the command to "tsc" and it worked perfectly, also the debugger was stopping in the right source file! :) I was curious to check the original version on GitHub, and it was working too, without the package.json file! I don't know why, maybe I was using an outdated TypeScript version. Thank you very much, you are great! :) – Brutus Feb 25 '16 at 11:12
  • But now I would like to use your way to go, I mean the TypeScript compiler installed locally to the project: do you have any idea about the error I'm getting? – Brutus Feb 25 '16 at 11:14
  • Try with updated tasks.json. It should work on windows. – Amid Feb 25 '16 at 11:37
  • It works, perfetct! Thanks again man! :) Currently I'm fighting against another issue about debugging ts files when compiling a single file; I edited this project and I'm able to debug correctly, but I have another one that is not working as expected. But in any case, that's another story, I'll try to fix it and in case I'll ask another question! Thanks a lot! :) – Brutus Feb 25 '16 at 13:14
  • The most important part of this for me is to ensure in launch.json that the "outDir": "${workspaceRoot}/bin" matches the correct destination for your compiled javascript files. – AdamH Jul 18 '16 at 00:44
2

Juli 2022 Nothing additional (like gulp etc.) is necessary

Step 1:

Simply install ts-node globally:

npm i -g ts-node

Step 2:

Add a new configuration in launch.json (VSCode). The following is for macOS; for other operating systems, modify the runtimeExecutable property accordingly:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "TypeScript Debugging",
      "type": "node",
      "request": "launch",
      "args": ["${relativeFile}"],
      "cwd": "${workspaceRoot}",
      "runtimeExecutable": "/opt/homebrew/bin/ts-node"
    }
  ]
}

Step 3:

Open the TypeScript file you want to debug and set a break point.

Step 4:

and click left on "Rund and Debug."

TypeScript Debugging in VSCode

Backup: tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "lib": ["ESNext", "DOM"],
    "module": "esnext",
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipDefaultLibCheck": true,
    "skipLibCheck": true,
    "sourceMap": true
  }
}

1

was having the same issue trying to figure out how to debug TS+nodejs with aws Lambda. Looks like the ts-node-dev package is faster than nodemon in terms of watch TS file changes.

npm install ts-node-dev --save-dev

finally add below config in launch.json:

{
  "version": "1.0.0",
  "configurations": [
    {
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "name": "Local Server",
      "restart": true,
      "request": "launch",
      "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/ts-node-dev",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "type": "node",
      "runtimeArgs": [
        "--respawn"
      ],
      "args": [
        "${workspaceFolder}/src/script/local.server.ts"
      ]
    }
  ]
}
    

Press F5 should launch your local server either with native http or express/koa/hapi... etc. Now you can set break points in code. Also the ts-node-dev will watch the TS file change and reload server on each save.

I wrapped up a small library for this if you happen to develop with aws lambda

https://github.com/vcfvct/ts-lambda-local-dev
LeOn - Han Li
  • 9,388
  • 1
  • 65
  • 59
0

This is how I am debugging my typescript (express) project. Use ts-node you don't have to compile manually . Using this configs i am directly debugging in my typescript files. Hope this helps someone.

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Current TS File",
      "type": "node",
      "request": "launch",
      "args": ["${workspaceRoot}/src/app.ts"],
      "runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
      "sourceMaps": true,
      "cwd": "${workspaceRoot}",
      "protocol": "inspector"
    }
  ]
}
Basanta Kc
  • 245
  • 4
  • 5