Inspecting Node.js with Chrome DevTools · Issue #2546 · nodejs/node (original) (raw)
Objective
We’ve been thinking about providing unified debugger support across various v8 embedders. One natural approach to that is to reuse Chrome DevTools and provide its JS debugger, performance and memory profiler functionality to Node.js users. What we aim for Node is what we have for Chrome for Android. You basically go to chrome://inspect on a stable version of Chrome and it debugs your running Node instance. You might need to override / specify ports to both if you want them to be non-default. The rest is behind the scenes.
Internal design
DevTools is comprised of the two major components: Frontend providing UI and Backend that instruments inspected application. Frontend is essentially a web application that communicates to the Backend via remote debugging protocol and nothing prevents it from connecting to Node.js instead of Chrome. To support that we’ll need to extract parts of debugger and profiler functionality from Blink into a separate project that would implement DevTools remote debugging protocol. Let’s call the project v8-inspector. Node.js could then expose the protocol to the Frontend over a WebSocket connection.
Proof of concept
I’ve created a prototype demonstrating this approach:
https://github.com/yury-s/v8-inspector - implementation of DevTools protocol for debugger, performance and memory profilers. I started with forking Blink and then removed dependencies that wouldn’t make sense in Node.js. There is definitely more work to be done but I believe this is good enough as a proof of concept.
https://github.com/yury-s/io.js/tree/remote-debugger - io.js clone that uses the project decribed above and ws module to allow using DevTools Frontend for debugging/profiling.
Local Node debugging scenario with custom ports would look like this:
- Start Node with --remote-debugging-port=9222 command-line flag
- Start Chrome with --remote-debugging-targets=localhost:9222 command-line flag
- Navigate Chrome to chrome:inspect to see list of inspectable Node.js targets
Longer term
Long-term solution would be to have both Blink and Node.js use the same native v8-inspector library linked against v8. DevTools Frontend development would continue in Blink. For each version of v8-inspector there is a compatible version of DevTools Frontend served from the cloud. This is how it works with Android debugging at the moment: when the user opens DevTools for Chrome running on Android, the desktop browser loads a version of DevTools UI corresponding to the version of Chrome running on Android and forwards all traffic from the device to that Frontend.
Open questions
Before moving forward with this approach and investing into Blink refactorings necessary for extracting common code into its own library we’d like to collect some feedback on whether Node.js community would be interested in that. In particular, is there an interest in integrating such debugger library into Node.js core?
- This will require compiling Node with the v8-inspector library and providing Node.js-specific implementation of interfaces required by the debugger.
- Remote debugging protocol will be exposed to third party Node.js modules as a simple API similar to what is available for Chrome extensions (https://developer.chrome.com/extensions/debugger). Client of such API should run on a separate thread not to interfere with JavaScript in the inspected Node application. In the prototype all debugger events are forwarded from the main thread to a node instance running on a separate thread.
- Implementing transport for the protocol. It can be a module that would use the debug API described above and send protocol commands over WebSocket. E.g. in the prototype it is a simple web server based on ‘ws’ module: https://github.com/yury-s/io.js/blob/remote-debugger/lib/remote_debugging_server.js. Bundling this module with the core would enable zero-conf rich devtools experience (on par with Chrome’s DevTools).
- As the project evolves it will require adding new instrumentation to use some new features such as asynchronous call stacks. On the DevTools side we’ll be providing generic API that would work for both Blink and Node.js
- There is some maintenance cost related to the debugger if Node.js decides to ship with it but I don’t expect it to be much higher than for the current debugger that includes debugger-agent.cc. Ideally, v8-inspector would be included as part of the v8 checkout and the obsolete debugging protocol implemented by v8 would be removed, but that is not a done deal yet.