Hacking how Node.js launches in Visual Studio Code
I've been using Visual Studio Code lately, working on getting my socket sever, Sir, off its feet. As any good dev will tell you, the first step for good debugging is good logging, so I was on the search for a small, fast Node.js logging module.
And thus I came across Bunyan.
Bunyan does a lot of things, but when you run it, a simple
log.info( "Hello world" );
becomes
{"name":"Sir","hostname":"divillysausa-PC","pid":2244,"level":30,"msg":"Hello world!","time":"2015-07-12T21:47:30.576Z","v":0}
in your console.
While undoubtedly useful, it also makes actually reading them a bit awkward. Happily, they've thought of this, and have included a CLI that takes that output and transforms it to:
[2015-07-12T22:12:45.698Z] INFO: Sir/4900 on divillysausa-PC: Hello world!
They've even colour coded it for your convenience!
Where Visual Studio Code comes in
All of this is relevant to the title, I promise.
In order to get this wonderful output, you simply need to change your node
call from
node app.js
to
node app.js | "node_modules/.bin/bunyan"
In essence, what you're doing here is piping the output coming from node
and sending it to bunyan
.
So, how do you actually do that?
The first time you hit F5 to launch your app, Visual Studio Code will create a launch.json file for you that looks like this:
{
"version": "0.1.0",
// List of configurations. Add new configurations or edit existing ones.
// ONLY "node" and "mono" are supported, change "type" to switch.
"configurations": [
{
// Name of configuration; appears in the launch configuration drop down menu.
"name": "Launch app.js",
// Type of configuration. Possible values: "node", "mono".
"type": "node",
// Workspace relative or absolute path to the program.
"program": "app.js",
// Automatically stop program after launch.
"stopOnEntry": false,
// Command line arguments passed to the program.
"args": [],
// Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.
"cwd": ".",
// Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH.
"runtimeExecutable": null,
// Optional arguments passed to the runtime executable.
"runtimeArgs": [],
// Environment variables passed to the program.
"env": {},
// Use JavaScript source maps (if they exist).
"sourceMaps": false,
// If JavaScript source maps are enabled, the generated code is expected in this directory.
"outDir": null
},
{
"name": "Attach",
"type": "node",
// TCP/IP address. Default is "localhost".
"address": "localhost",
// Port to attach to.
"port": 4000,
"sourceMaps": false
}
]
}
I tried adding my | "node_modules/.bin/bunyan"
line first in args
, then runtimeArgs
, then env
, before finally realising that these were being passed to your app.js program rather than to node
itself. Then I tried modifying the program
parameter to read "app.js | \"node_modules/.bin/bunyan\""
, but it complained that the file didn't exist :)
The key to getting this hack working is with the runtimeExecutable
property. By default it's null
, which means that VSC will search in your PATH
directory for node
. If you specify a path, then VSC will run that instead.
With that in mind, I created a small bat file (I'm on Windows), nodeWithBunyan.bat:
@echo off
node %* | "node_modules/.bin/bunyan" -o short
Basically, what it's doing is calling node
, passing all the parameters that VSC is passing (%*
), before piping the output through bunyan
(the -o short
at the end is just telling bunyan
to use its "short" output mode, which is even more concise). As we're passing all the VSC parameters, we even get to keep debugging.
If you're working in a bash environment, then I think the equivalent is
node $@ | ./node_modules/.bin/bunyan -o short
Back in VSC, we replace the runtimeExecutable
property so it reads
"runtimeExecutable": "./nodeWithBunyan.bat"
hit F5, and *jazzhands*!
If, for some reason, you want to switch between the default launch and the new, snazzy one, you can simply create another config, add it to the configurations
array in your launch.json file, then choose between them in dropdown menu on the Debug tab.
You can also use this technique if, for example, you want to set the DEBUG
or NODE_DEBUG
environment variables when launching:
NODE_DEBUG=http,fs,timers node %*
Enjoy!
Comments
I was trying to figure out how I should feed my 50+ environment variables (stored in a file) into the debug session without manually adding them to launch.json. This post was very helpful. Thanks :)
Hooray! I've been wrestling with a webpack dev server issue and your .bat file solution is inspired. Solved my problem. Thanks!
Great post and thank you very much :)
FYI in Linux this would be an .sh file with contents :
#!/bin/bash node "$@" | bunyan
Don't forget to
chmod +x yourFile.sh
Thanks again !
Awesome! Works great, which it could be colored :-)
This is awesome thanks!
thanks a lot, and it is a great job
Submit a comment