angularvisual-studio-codewebpackvscode-debuggersource-maps

How can I bind break points in both my Angular application and library in VSCode, I can only get working in one or the other, not both


I am attempting to get debugging in vscode working for both my application and my lib for Angular 16 at the same time. The structure is as follows:

./root
./root/my-app/src
./root/lib/projects/my-lib

I have added my lib to the app's project.json and have been able to successfully install, build, watch and update both the app and the lib and have it hot reload, however I can only get the breakpoints working in one or the other, but not both at the same time. I have set webRoot in the launch.json file to the ./root folder and have tried path overrides like below. (I realize I can't have two enties for "webpack:/*", I'm just showing what I'm successful with when I change between the two.)

"webRoot": "C:\\path\\to\\root",
"sourceMapPathOverrides": {
  "webpack:/*": "${webRoot}/my-app/*", // works for app, but not lib
  "webpack:/*": "${webRoot}/lib/*", // works for lib, but not app
}

When I use vscode's Debug Diagnotics and see why the source wasn't loaded, I get a message like this when I use the "lib" entry from above:

We couldn't find a corresponding source location, but found some other files with the same name:

  c:\path\to\root\lib**my-app**\src\app\features\component\component.ts

In the above, **my-app** is red and strike though and lib is green.

Is there a way to make this work? I was thinking all I needed to do was create an entries like "webpack:/my-app/*" and/or "webpack:/lib/*" but neither of those work for either one.

Any help would be greatly appreciated!


Solution

  • If anyone runs into this, it took me way too long to even think I know how it works, because I still don't really understand it but I'll attempt to provide an explanation of what I did in order to fix my scenario.

    TLDR;

    "webRoot": "${workspaceFolder}/../",   // need to jump out of ./root/my-app to ./root
    "sourceMaps": true,
    "sourceMapPathOverrides": {
    
      // map ./projects/* to ./root/lib/projects
      "webpack:///./projects/*":  "${webRoot}/lib/projects/*",
    
      // map ./src/* to ./root/my-app/src/*
      "webpack:///./src/*":       "${webRoot}/my-app/src/*"
    
    }
    

    NTLDR;

    (Not too long, did read.) :)

    webRoot

    My app source is essentially a sibling of my lib source (they both live in the ./root folder) and the vscode ${workspaceFolder} variable points to the root of it's project so in my case the value of ${workspaceFolder} is ./root/my-app because it is located at ./root/my-app/.vscode/launch.json. I needed the value of ${webRoot} to be the parent directory of my-app (./root), so: "webRoot": "${workspaceFolder}/../" It might be possible to leave that alone and only make the change to the actual path override, but I didn't try.

    sourceMapPathOverrides

    The source maps are loaded into a special webpack:/// path that you can view in vscode or chrome.

    vscode

    chrome

    Both of those pointed to these paths I needed to override:

    solution

    Even after I had the paths, it seemed like nothing I tried in was taking effect so I started second guessing those were the correct paths which turned into a vicious cycle of bad guesses, paths and patterns that would never work.

    As it turns out, I needed to use "webpack:///./" as the prefix for my override entries/pattern and boom! break points hit in both app and lib when debugging using the my-app launch config.

    According to my new best friend, ChatGPT, here is an explanation of "webpack:///./":

    Hope this helps someone else down the road, it took me waaaay to long to figure this out...for some reason I just couldn't wrap my head around the obvious.

    Here is my launch.json and tasks.json file:

    {
      "version": "0.2.0",
      "configurations": [
        {
          "name": "Debug MyApp",
          "type": "chrome",
          "request": "launch",
          "preLaunchTask": "Serve MyApp",
          "url": "http://localhost:4200/#",
          "webRoot": "${workspaceFolder}/../",
          "sourceMaps": true,
          "sourceMapPathOverrides": {
            "webpack:///./projects/*":  "${webRoot}/lib/projects/*",
            "webpack:///./src/*":       "${webRoot}/my-app/src/*"
          },
          "trace": true
        }
      ]
    }
    
    {
      "version": "2.0.0",
      "tasks": [
        {
          "label": "Serve MyApp",
          "type": "npm",
          "script": "start",
          "isBackground": true,
          "presentation": {
            "focus": true,
            "panel": "dedicated"
          },
          "group": {
            "kind": "build",
            "isDefault": true
          },
          "problemMatcher": {
            "owner": "typescript",
            "source": "ts",
            "applyTo": "closedDocuments",
            "fileLocation": ["relative", "${cwd}"],
            "pattern": "$tsc",
            "background": {
              "activeOnStart": true,
              "beginsPattern": {
                "regexp": "(.*?)"
              },
              "endsPattern": {
                "regexp": "Compiled |Failed to compile."
              }
            }
          }
        }
      ]
    }