Running a dedicated local server for a VS Code debugging session using tasks

Christian Heilmann - Mar 17 '22 - - Dev Community

Back in January, I wrote about a launch.json file to turn VS code into an end-to-end web debugging environment. One of the features people told me was missing was to start and stop a server with the debugging session. So here is how to do this.

We add two more lines to the existing launch.json, defining a task to run before debugging starts and one after it ends. Let's call them start server and stop server respectively:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "pwa-msedge",
            "request": "launch",
            "name": "webdebug",
            "url": "http://localhost:8080",
            "webRoot": "${workspaceFolder}",
            "runtimeExecutable": "stable",
            "runtimeArgs": ["--headless"],
            "preLaunchTask": "start server",
            "postDebugTask": "stop server"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

We then need to create a tasks.json file in the .vscode folder that describes these tasks. Here is the final result:

{
  "version": "2.0.0",
  "tasks": [
    {
        "label": "start server",
        "type": "shell",
        "isBackground": true,
        "command": "http-server",
        "presentation": { "reveal": "silent" },
        "problemMatcher": [{
          "pattern": [{
            "regexp": ".",
            "file": 1,"line": 1,
            "column": 1,"message": 1
          }],
          "background": {
              "activeOnStart": true,
              "beginsPattern": { "regexp": "." },
              "endsPattern": { "regexp": "." }
          },
        }]
    },
    {
        "label": "stop server",
        "command": "echo ${input:terminate}",
        "type": "shell"
    },
  ],
  "inputs": [{
    "id": "terminate",
    "type": "command",
    "command": "workbench.action.tasks.terminate",
    "args": "terminateAll"
  }]
}
Enter fullscreen mode Exit fullscreen mode

Tasks are meant to run, have an end and then tell the debugger that they are ready. Normally you would, for example, use them to do some conversion or pull some information. In this case, it is a bit trickier, as we start a server and that doesn't give us any feedback. The task never ends as the server starts and keeps running.

The start server task is a shell task, should run in the background and the command it executes is http-server, which is the NPM module of the same name. The presentation property is set to silent, which means that when the server starts, it doesn't pop up the terminal in Visual Studio Code. When we use background tasks, we need to define a problemMatcher that tells the debug process if the task has executed successfully or if there was any issue. This can get rather complex and you need to parse the output on the Console with Regular Expressions. In this case, we keep it very open and allow anything reported on the output Console to be a success (RegEx ".").

What this task does is open a new Terminal, enter "http-server" and hit enter for us. And once that's done, we have a local server at our disposal, making the current Workspace folder available as localhost:8080, which is also what we defined in our launch.json as the address to navigate to.

The stop server task is a bit simpler. we just make it send a terminate command to the terminal. We then use an inputs directive to define the terminal CLI command as something that calls workbench.action.tasks.terminate with an argument of terminateAll. This closes any Terminals opened by tasks earlier.

And that's all there is to spawn a new local server when you start debugging and close it when the debug session ends.

There is currently a bug in VS Code, that throws an error in your tasks when the Problems pane is not empty when the task runs. In the case of using the Edge Developer tools for VS Code extension that means any issue reported there will result in this problem. I reported this to the team and they are working on a solution.

If you want to see this in action, you can fork the simple to-do demo and run it locally. Make sure to have http-server installed via NPM.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .