使用VS Code调试在Docker容器中使用ts节点运行的TypeScript应用程序时,如何正确设置断点?

时间:2021-10-02 21:22:39

Our app is written in TypeScript and uses Docker, and to avoid round-tripping through .js files, we're running it with ts-node to load the .ts files directly.

我们的应用程序是用TypeScript编写的,并使用Docker,为了避免通过.js文件进行往返,我们使用ts-node运行它来直接加载.ts文件。

Unfortunately this seems to make VSCode confused as to where valid lines of code are for setting breakpoints.

不幸的是,这似乎使VSCode对于有效的代码行设置断点的位置感到困惑。

This problem manifests with the following setup:

此问题通过以下设置显示:

/package.json

{
  "scripts": {
    "start": "node --inspect=0.0.0.0 --require ts-node/register src/index.ts"
  },
  "dependencies": {
    "@types/node": "^10.1.2",
    "ts-node": "^6.0.3",
    "typescript": "^2.8.3"
  }
}

/tsconfig.json

{
  "compilerOptions": {
    "target": "ES2017",
    "module": "commonjs", 
    "outDir": "./dist",
    "rootDir": "./src",    
    "esModuleInterop": true
  }
}

/Dockerfile

FROM node

RUN mkdir /home/node/app
WORKDIR /home/node/app
COPY package.json /home/node/app
RUN npm install && npm cache clean --force
COPY . /home/node/app
CMD [ "npm", "start" ]

/docker-compose.yml

version: "3.4"

services:
  http:
    build: .
    ports:
      - "8000:8000"
      - "9229:9229"

/.vscode/launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "attach",
            "name": "Attach",
            "address": "localhost",
            "port": 9229,
            "protocol": "inspector",
            "localRoot": "${workspaceFolder}/src",
            "remoteRoot": "/home/node/app/src"
        }
    ]
}

/src/index.ts

import {createServer} from "http";








const server = createServer((msg, res) => {
    res.writeHead(200, {'Content-Type': 'text/plain'})
    res.end(msg.url)
    debugger
})

server.listen(8000)

(The blank lines are significant for reasons I'll show later, about ten of them does the job.)

(空白行很重要,原因我稍后会说明,其中大约有十个人完成这项工作。)

You can also fetch the whole thing here: https://github.com/millimoose/ts-node-breakpoints

你也可以在这里获取整个内容:https://github.com/millimoose/ts-node-breakpoints

I run this with docker-compose --up, then attach to that with the debugger using the above launch configuration. When I try to set breakpoints in /src/index.ts on any of the lines inside the createServer() call, they're reported as invalid; while I can set breakpoints in the blank lines. This is presumably because TypeScript compilation strips the blank lines, and for some reason, VSCode will only recognize line numbers from the generated JS as valid:

我用docker-compose --up运行它,然后使用上面的启动配置通过调试器附加到它。当我尝试在createServer()调用中的任何行上的/src/index.ts中设置断点时,它们被报告为无效;虽然我可以在空行中设置断点。这可能是因为TypeScript编译剥离了空行,出于某种原因,VSCode只会将生成的JS中的行号识别为有效:

使用VS Code调试在Docker容器中使用ts节点运行的TypeScript应用程序时,如何正确设置断点?

This is a contrived example for ease of reproduction, but in general there'll be a mismatch between where I think I'm setting breakpoints, and where they're actually set.

这是一个易于复制的人为例子,但总的来说,我认为我在设置断点的位置与实际设置的位置之间存在不匹配。

However, when I break on the debugger statement, VSCode fetches the TypeScript file (the tab says something along the lines of "read-only inlined from sourcemap" when newly opened) from the server, and I can then set breakpoints correctly in it:

但是,当我打破调试器语句时,VSCode从服务器获取TypeScript文件(该选项卡在新打开时显示“从源映射中只读内联”的行),然后我可以在其中正确设置断点:

使用VS Code调试在Docker容器中使用ts节点运行的TypeScript应用程序时,如何正确设置断点?

This is an unsatisfying situation for reasons I shouldn't have to explain: juggling a local file I can edit and a remote file where breakpoints work is a hassle, and adding debugger statements would involve reloading the app everytime I need a new breakpoint.

这是一个令人不满意的情况,原因我不应该解释:杂乱我可以编辑的本地文件和断点工作的远程文件很麻烦,添加调试器语句将涉及每次我需要一个新的断点时重新加载应用程序。

I've searched around for the issue, but the keywords give me at least ten lengthy GitHub issues ranging as far as years back. Since I'm not intimately familiar with the internals of ts-node, transpilation, and sourcemaps, I'm having a hard time reasoning through what's going on here, much less how to fix it. From what I understand, what happens is that ts-node compiles TS to JS and generates sourcemaps in temporary files inside the Docker container where VSCode can't access them. (This is why I've no idea how to set e.g. outFiles.) There were also some allusions to my scenario being already supported if set up correctly in closed issues, but no clue as to how to do it.

我一直在寻找这个问题,但关键词给了我至少十年冗长的GitHub问题。由于我对ts节点,转换和源图的内部结构并不熟悉,因此我很难理解这里发生的事情,更不用说如何解决它了。根据我的理解,会发生的事情是ts节点将TS编译为JS并在Docker容器内的临时文件中生成源映射,而VSCode无法访问它们。 (这就是为什么我不知道如何设置例如outFiles。)如果在封闭的问题中正确设置,我的场景中也有一些暗示已被支持,但没有关于如何做到这一点的线索。

Is there a way to get this working so that I can actually set a breakpoint in my local sources when remote-debugging, and have them hit in said files, without having to revert to precompiling TS to JS and sourcemaps so I have the latter available locally?

有没有办法让这个工作,以便我可以实际在远程调试时在我的本地源中设置断点,并让它们在所述文件中命中,而不必恢复到TS到JS和源映射的预编译所以我有后者可用本地?

1 个解决方案

#1


5  

Your are not generating source map for the code. So I updated your tsconfig.json like below

您没有为代码生成源映射。所以我更新了你的tsconfig.json,如下所示

{
  "compilerOptions": {
    /* Basic Options */
    "target": "ES2017",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "outDir": "./dist",                        /* Redirect output structure to the directory. */
    "rootDir": "./src",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    "sourceMap": true,
    "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
  }
}

and now it works like a charm

现在它就像一个魅力

使用VS Code调试在Docker容器中使用ts节点运行的TypeScript应用程序时,如何正确设置断点?

#1


5  

Your are not generating source map for the code. So I updated your tsconfig.json like below

您没有为代码生成源映射。所以我更新了你的tsconfig.json,如下所示

{
  "compilerOptions": {
    /* Basic Options */
    "target": "ES2017",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "outDir": "./dist",                        /* Redirect output structure to the directory. */
    "rootDir": "./src",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    "sourceMap": true,
    "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
  }
}

and now it works like a charm

现在它就像一个魅力

使用VS Code调试在Docker容器中使用ts节点运行的TypeScript应用程序时,如何正确设置断点?