VS Code: open browser when application server is ready

A golden standard: launching a project with a single action

When we set up a project, I think it’s of great value to allow to build and launch the project with a single action. Developers launch their code dozens of times a day, so it’s a worthwhile optimization.

Example: building and launching project with a single button in Visual Studio

The action to launch a project would typically be:

  • Clicking a single button in the IDE
  • Using a single keystroke in your IDE (like F5 in Visual Studio),
  • Or at least launching a single build file, e.g., named start.bat.

What exactly should the “launch” action do?

In front-end projects, I like the launch action to do three things:

  1. Build the application
  2. Launch a web server serving the application
  3. Open the browser with the URL most likely needed by the developer

The choice of what page to open is not always obvious and might depend on the developer’s work. It seems reasonable to open one of the following:

  • In web projects:
    • A home page of the application (if possible, the development variant with hot-reloading),
    • A Storybook instance (if our workflow is driven by such a tool)
    • A specific route useful for development on a given day (e.g., a login page or a frequently modified section)
  • In backend projects:
    • A Swagger UI endpoint, allowing crafting quick requests to test the backend
    • A GraphQL Playground (if the project uses GraphQL)
    • An admin dashboard (e.g., in Content Management Systems)
    • A monitoring page showing live logs

VS Code: wait to open the browser until the server is ready

Today, I’ll share a recipe for configuring the Visual Studio Code project so it waits for the specific message to appear in the server’s output before opening the browser window. For example, we can wait for a message like:

  VITE v6.0.11  ready in 6774 ms
  ➜  Local:   http://localhost:5173/
Code language: JavaScript (javascript)

Waiting gives us benefits:

  • We avoid the “404 not found” page being displayed if the browser opens too early
  • We can capture the correct port number instead of hardcoding it

I’m sharing this recipe because it’s not documented comprehensively, and even modern AI tools like o3-mini had trouble implementing it correctly.

The solution: a minimal project in VS Code

Here’s a minimal Node.js project showing the problem and solution.

package.json

{
  "name": "myproject",
  "version": "1.0.0",
  "scripts": {
    "start": "timeout /t 4 && npx serve"
  }
}
Code language: JSON / JSON with Comments (json)

Here, we declare a script named start. The script waits for 4 seconds (an artificial delay for demo purposes) and launches the npx serve tool, which serves the contents of the current directory in a browser.

launch.json

The fun part is in the launch.json file. Here, we can specify that we run the start script and wait for a specific line (that matches the pattern Regex) to appear in the terminal. When it does, we open the browser with a URL defined in uriFormat property. The %s is whatever was captured by the first regex group in the pattern:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Start debugging and open Chrome",

      "type": "node-terminal",
      "request": "launch",
      "command": "npm run start",

      "serverReadyAction": {
        "action": "debugWithChrome",
        "pattern": ".*http://localhost:(\\d*).*",
        "uriFormat": "http://localhost:%s"
      }
    }
  ]
}
Code language: JSON / JSON with Comments (json)
The browser is launched only when the log appears in the output of the launched process.

Gotcha: The browser doesn’t open despite serverReadyAction.pattern Regex’s presence

There is one interesting issue you might encounter is that the browser might not open despite the pattern looking fine at first glance.

It’s worth noting that many web servers output their logs in color or with another kind of console formatting. In such a case, your regex will be matched against lines of text that aren’t plain text but text with various escape sequences. My example above, in reality, is matched with a line like:

│ - Local: http://localhost:3000 │

So, between the word Local and the URL, we do not only have whitespace but escape characters, too. Your Regex should consider that. There is no single standard to disable formatted output in all console tools, so your workaround for this problem might vary.

Example code for this blog post can be found in my GitHub repo.

No comments yet, you can leave the first one!

Leave a Comment