How Do I Debug An Angular 7 Library in Visual Code - node.js

Is it possible to use Visual Studio Code Debugger to debug an Angular Library that has been linked using npm link? Very specifically I am wondering if I can link the debugger to my library's TypeScript Code (not the built js code).
My debugger works fine for the application I am running through the VS Code, however my linked library breakpoints are never hit.
From the research I have done I believe I understand why this is happening (the app using the library does not have the source, it only has the compiled code within node_modules) however I cannot figure out or find any details on how to debug.
Here is an overview of what I have done:
Angular 7 library built into dist folder.
I ran npm link within the dist folder
I ran npm link #my/test-lib in my application, the library shows up in node_modules and the application is able to use it just fine
in angular.json: sourceMap is true, preserveSystemlinks is true, aot is false, vendorSourceMap is true
tsconfig.json sourceMap is true, enableResourceInlining is true
vscode launch.json has runtimeArgs set to --preserve-symlinks and --preserve-symlinks-main

I'm posting just to provide a clearer example to #SyncingDisks solution:
You actually don't need the full path, ${workspaceFolder} would do the job also:
"webpack:///ng://angular-reporting/lib/*": "${workspaceFolder}/projects/angular-reporting/src/lib/*"
which would fit in launch.json as follows:
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome",
"url": "http://localhost:4200",
"webRoot": "${workspaceFolder}",
"sourceMapPathOverrides": {
"webpack:///ng://angular-reporting/lib/*": "${workspaceFolder}/projects/angular-reporting/src/lib/*"
},
}
Don't forget to add --vendorSourceMap to ng serve which would become:
ng serve --vendorSourceMap
Update:
for Angular 7 and higher update the "angular.json" file instead of adding "--vendorSourceMap" to "ng serve":
"serve": {
"builder": "#angular-devkit/build-angular:dev-server",
"options": {
"sourceMap": {
"scripts": true,
"styles": true,
"vendor": true
},
...
}
}

Fine tune your launch.json based on the sourceMapPathOverrides. Excerpt from mine:
"sourceMapPathOverrides": {
"webpack:///ng://<<your-awesome-lib>>/lib/*": "C:/<<full path to your library wrapper app>>/projects/<<your-awesome-lib>>/src/lib/*"
},

Related

How to debug node.js dependency packages in TypeScript with VS Code

Assuming we have two node.js projects with the following structure:
Project Foo has Bar as a dependency by declaring the following in its package.json:
{
"scripts": {
"start": "ts-node src/index.ts --transpile-only --no-lazy"
},
"dependencies": {
"bar": "file:../Bar"
}
}
And I configure VSCode's debugger with the following launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "start",
"request": "launch",
"runtimeArgs": [
"start"
],
"runtimeExecutable": "npm",
"smartStep": true,
"type": "node"
}
]
}
And the problem is when I step into a function imported from Bar during debugging, it'll go into a temporary compiled js source instead of the original TypeScript source, no matter I define Bar's package main entry as src/index.ts or lib/index.js. Besides, if I add breakpoints in Bar's typescript sources, they won't even be loaded.
How can I make the debugger load Bar's breakpoints, and go directly into the TypeScript sources when debugging Foo? Should I modify some properties in launch.json, or pass some more options to ts-node in the start script?
To better illustrate this problem, I've uploaded the two demo projects to GitHub: StackOverflow-Demo
You should be able to do this by configuring source maps.
See the sourceMap field or the inlineSourceMap field of tsconfig. See also VS Code's guide on Debugging TypeScript.
From the VS Code docs' section on "Mapping the output location":
If generated (transpiled) JavaScript files do not live next to their source, you can help the VS Code debugger locate them by setting the outFiles attribute in the launch configuration. Whenever you set a breakpoint in the original source, VS Code tries to find the generated source by searching the files specified by glob patterns in outFiles.

Unbound breakpoints in Docker node.js TypeScript application

There are a lot of questions on this topic, and I have tried many of the solutions that worked for others, but the solution seems to depend on several things such as the version of VS Code and the recipe used.
This is my VS Code Help>About info:
Version: 1.60.2 (user setup)
Commit: 7f6ab5485bbc008386c4386d08766667e155244e
Date: 2021-09-22T12:00:31.514Z
Electron: 13.1.8
Chrome: 91.0.4472.164
Node.js: 14.16.0
V8: 9.1.269.39-electron.0
OS: Windows_NT x64 10.0.17763
The OS is Windows 10.
The Docker plugin is installed.
I have Docker Desktop 2.3.0.3 installed.
The application is written in TypeScript with inversify IOC.
I am using the launch.json and tasks.json files in src/.vscode.
The Docker container is built with the contents of the workspacefolder in /app. It is running locally, using the VS Code Docker plugin.
launch.json:
{
"configurations": [
{
"name": "Docker Node.js Launch",
"type": "docker",
"request": "launch",
"port": 9229,
"protocol": "inspector",
"preLaunchTask": "docker-run: debug",
"localRoot": "${workspaceFolder}/",
"platform": "node",
"remoteRoot": "/app/",
"sourceMaps": true,
}
]
}
tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"type": "docker-build",
"label": "docker-build",
"platform": "node",
"dockerBuild": {
"dockerfile": "${workspaceFolder}/Dockerfile",
"context": "${workspaceFolder}",
"pull": true
}
},
{
"type": "docker-run",
"label": "docker-run: release",
"dependsOn": [
"docker-build"
],
"platform": "node"
},
{
"type": "docker-run",
"label": "docker-run: debug",
"dependsOn": [
"docker-build"
],
"dockerRun": {
"env": {
"DEBUG": "*",
"NODE_ENV": "development",
},
"command": "node --inspect-brk=0.0.0.0 dist/index.js",
"envFiles": [".env"],
},
"node": {
"enableDebugging": true,
"inspectPort": 9229
}
}
]
}
tsconfig.json:
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"noImplicitAny": true,
"strictNullChecks": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true,
"outDir": "./dist/",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"typeRoots": [ "./types", "./node_modules/#types"],
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "src/**/*.test.ts", "types", "**/tests/*.ts"]
}
When I initiate debug (select the Docker Node.js Launch option and hit F5), the docker builds and starts. The application stops on the first line of dist/index.js, but all my breakpoints (which are all in classes) show as unbound and the debugger does not stop on any of them. The application runs normally otherwise.
I assume that the breakpoints are unbound because VS Code can not map the running code back to the breakpoints in the source. But I have tried opening the files inside the container and setting breakpoints there, and that doesn't work either.
What do I have to do to make breakpoints work?
I had a similar issue today and was finally able to solve it. I will provide my findings here in the hope it might be helpful to you too.
1. Use trace
By setting trace: true in the launch.json configuration, you will get a lot of more details in your logs.
You can read how to make use of that here: NodeJs Debugging in Visual Studio Code
When starting the debugger config with trace: true, you will get a log entry in your debug console in the likes of
Verbose logs are written to:
/somepath/vscode-debugadapter-xxxxxx.json.gz
You can take this logfile and analyze it here in this interesting online tool by Microsoft: vscode-pwa-analyzer (Whole Project on Github)
There's a whole lot of logs in there. Probably best if you just try it out and see if you see anything helpful in there.
2. check your sourcemaps
For me it really helped to look at one of my sourcemap files. Go to your build / dist or whatever name you use for your build directory and look for a .map File.
If you open it, you should see something along the lines of
{"version":3,"file":"somefile.js","sourceRoot":"","sources":["../../../src/somedir/somefile.ts"] ... }
Make sure that the sources path is correct. Otherwise there might be something off with your tsconfig File.
3. check the outFiles config
This seemed to be necessary for me to configure to make it work. Add all the paths as glob patterns that contain compiled Javascript Files.
"outFiles": ["${workspaceFolder}/dist/**.js"],
4. sourceMapPathOverrides
There might also be an issue with the Source Map Paths. You can see if adding this snippet here helps:
"sourceMapPathOverrides": {
"webpack:///./*": "${workspaceRoot}/*",
},
5. check the program config
For me, adding the program config property finally did the trick.
If you don't know which one that might be, in my case it helped looking at what my Chrome used as the entry File.
Go to chrome://inspect in your Chrome Browser while your application is started and check what you see there.
In this example the entry File would be the server.js, which led me to configure the source of that file as the program, (with the local path) like so:
"program": "${workspaceFolder}/src/server.ts"
Conclusion
Your setup is probably different from mine and I still don't understand all the settings 100% to be honest. But maybe one of these things helps you get closer to find a solution. Let me know if it helped, and good luck.

VS Code Debugger: How to Attach to Chrome Tab served by browser-sync?

I am having trouble finding a solution for running the VS Code integrated Debugger with Browser-Sync. Instead of launching chrome with the VS Code Debugger, my current launch.json looks like this:
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Chrome",
"port": 9222,
"request": "attach",
"type": "pwa-chrome",
"url": "http://localhost:3002",
"webRoot": "${workspaceFolder}/dist"
}
]
}
This solution let's me launch browser-sync via my taskrunner ("gulp") in my terminal, however, it does not let me set breakpoints within VS Code:
As soon as I pause the debugger, I will end up somewhere in the depths of the browsersync.js files (see Screenshot here)
Is there a better way of debugging within VS Code whilst using gulp and retaining automatic browser reload?
Ok, after making the comment I decided to give another try and it seems that everything is working finally!
My case is a little bit special because I have a browser-sync setup mapping to several other folders + typescript compilation + rollup + multi-root workspace + an in-house made framework + other things to handle. But in the end, a simple solution was the one that worked for me:
{
"version": "0.2.0",
"configurations": [
{
"type": "pwa-chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:3000",
"pathMapping": {
"/": "${workspaceFolder}/dist",
}
}
]
}
The thing here is the pathMapping property that helps the debugger find the source map files. In my case, these files are mapped (with browser-sync) to the '/' path but they are inside the '/dist' folder inside my project root.
Keep in mind that if you have typescript source files like I do, you absolutelly need to generate source map files setting "sourceMap": true inside your tsconfig.json file.
EDIT Another thing that I forgot to mention is that the browser-sync server must be running in another terminal before you start the debug.

Debugging nuxtjs .vue Files On the Server in Docker

I currently have a nuxt app setup as a univeral app in which I'm hosting using Docker. I've got pretty much everything working, the debugger attaches and finds local variables just fine when walking through middleware and api calls, but when debugging the asyncData method in the .vue file I can't see any of the local variables and my breakpoint keeps moving to the .catch line:
I also get a bunch of other random things in the current context, which in this case is "Module"??
I've added this line to my nuxt.config.js file as well to make sure it uses the correct source maps:
/*
** Build configuration
*/
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {
console.log(`IsClient: ${ctx.isClient}`);
console.log(`isDev: ${ctx.isDev}`);
if (ctx.isDev) {
config.devtool = ctx.isClient ? 'source-map' : 'inline-source-map'
}
}
}
Also here is my .vscode config:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Docker: Attach to Node",
"type": "node",
"request": "attach",
"remoteRoot": "/usr/share/nginx/app",
"port": 9229,
"address": "localhost",
"localRoot": "${workspaceFolder}/app",
"protocol": "inspector",
"restart": true,
"sourceMaps": true
}
]
}
Also, here is the command I use to start the container:
node --inspect=0.0.0.0:9229 \
./node_modules/.bin/nuxt \
& nginx -g "daemon off;" \
I've tried a lot of different things including using babel-register and starting it with babel-node since its transpiled, but none of those methods worked.
Is there anything I'm missing here? Can we just not debug .vue files on the server when creating a universal app?
UPDATE
I switched to Webstorm and for whatever reason the debugging works flawlessly. I guess that is the difference between using an IDE and a text editor.
vs code attach inspector when your nuxt app is already started.
To see whats happen in server side, vs code have to launch your nuxt app.
Add this script to your package.json:
...
scripts: {
"dev": "nuxt,
"dev-debug": "node --inspect node_modules/.bin/nuxt",
...
}
...
In .vscode config or .vscode/launch.json:
"configurations": [{
"type": "node",
"request": "launch",
"name": "Launch nuxt",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
"dev-debug"
],
"port": 9229
},
...
And finally, extend the build in nuxt.config.js to add source maps when we are running in development mode and ensure the correct type for both the client and server.
build: {
extend(config, ctx) {
if (ctx.isDev) {
config.devtool = ctx.isClient ? 'source-map' : 'inline-source-map'
}
}
}
It's work for me on localhost, but I'm not sure it's working with remote root...
Also, it's not a perfect solution. I saw sometimes breakpoint jump from different line. I think this is because vs code cannot handle same lines in source and inline-source.
Alternative way:
To debug only javascript of a single file component (.vue), it's possible to extract the javascript part in an external .js file, and import it with <script src="./path-to-js"></script>.

How to start developping with TypeScript and NodeJS in VSCode

I used to develop web sites with C# or Javascript with Visual Studio and IIS.
I've decided to upgrade to newer tools and try to create a simple web site with VSCode, NodeJS and TypeScript that I'll deploy to Azure later but each time I try a new sample, I get lost as I have the feeling it doesn't do what I want.
I created a TSConfig.json file with this minimum, I understood it creates a "project" in TypeScript:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"sourceMap": true
}
}
A simple main.ts file:
class Startup {
public static main(): number {
console.log('Hello World');
return 0;
}
}
Startup.main();
A simpliest index.html file that references the generated main.js file
I wanted to
- compile my web site using "$tsc-watch" to benefit from that automatic recompile
- launch the web site in NodeJS
- Open the web page in Chrome and being able to debug
But I am wondering, is it the right approach ? Should it be a tasks.json file that each time runs "$tsc-watch", launch the web site in Node and opens Chrome ?
I started with this tasks.json file :
{
"version": "2.0.0",
"tasks": [
{
"type": "typescript",
"tsconfig": "tsconfig.json",
"problemMatcher": [
"$tsc-watch"
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Chrome",
"type": "process",
"command": "chrome.exe",
"windows": {
"command": "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"
},
"args": ["./index.htm"],
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
Then, VSCode created a launch.json file but I'm not sure why and where it fits in the picture:
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}"
}
]
}
Would you be able to help me understand what I am doing wrong here and what I need to simply debug my application in VSCode as I would pressing F5 in VSStudio.
Thank you for any help,
Claude
It looks like you're trying to create the entire build-chain and configuration yourself. I recommend starting with a tool that handles the initial bootstrapping for you. For exampe, use the vue-cli tool to bootstrap a vue.js project with TypeScript. While it may include a little bit of spin-up in understanding vue.js, the vue-cli tool lets you select options (e.g. TypeScript) and auto-generates a project for you. Then, just open the newly created folder in Visual Studio Code and start playing around.
Once you get a feel for how it all ties together, you can add VSCode specific tasks, start modifying configurations, etc.
There are a number of good tutorials on vue.js and, in practice, you'll probably want to leverage a front-end framework when building any real application anyway.
See the following links for tutorials and more information:
vue-cli
vue.js

Resources