In this post I’m going to cover a few techniques that you can use when debugging library-related issues in your Node.js applications.
I’ll be using Vite.js as an example, as it provides an opportunity to cover some specifics related to debugging TypeScript packages and mono repos, but you can apply these techniques to debug any library.
Debug Output 📜
To enable logging for these libraries, set the
DEBUG environment variable:
DEBUG=*Enable all debug output
DEBUG=vite:*Enable output for Vite.js core plugins
DEBUG=vite-plugin-ruby:*Enable output for a specific plugin
Using a Debugger 🎯
node --inspect-brk will break execution until a debugger client is attached. You must provide a JS executable as an argument, for example:
node --inspect-brk "$(npm bin)/vite"
node --inspect-brk $(yarn bin vite)
inspectshortcut in your
scriptsif you need to debug often.
I like to use the Node Inspector Manager extension, which will automatically attach the browser’s DevTools to the node process.
DevTools provide a great debugging environment, with visual breakpoints, watchers, file navigation, and more. Visual Studio Code is another great option.
It’s useful to ignore Node.js internals to avoid stepping into the framework.
Opening Packages 📖
In order to learn more and understand which files you should be debugging, you can run
npm edit to open a package in your favorite text editor.
EDITORenvironment variable will be used to infer the preferred text editor. I like using Sublime Text or Visual Studio Code to navigate the file tree.
For example, running
npm edit vite will open the copy of the
vite package that is installed in the
node_modules for the current directory.
Unlike the previous sections, this is something you can leverage for client-side packages as well.
Editing In-Place ✍️
Disclaimer: This has many caveats: bugs that only happen in your local, or the opposite, code that only seems to work in your local.
(I use it all the time though, so convenient 😅)
You can add
console.log as needed, or even modify the behavior of the library, which can be useful to track down bugs.
In TypeScript packages (and some JS packages), make sure to edit the transpiled file instead of the sources. This is often
dist/index.js but that depends on the library and target environment.
For example, in Vite.js the entrypoint is
Using a Local Library 🔗
Let’s see a step by step example with
# 1. Clone the repo git clone firstname.lastname@example.org:vitejs/vite.git cd vite/packages/vite # Location of package.json yarn install # 2. Make the local package available for linking yarn link # 3. Start compilation in "watch" mode yarn dev
In TypeScript or compiled JS libraries, it’s important to build the library in order for changes to the source to be reflected in the linked project.
By convention, libraries define a
buildscript to perform compilation, and a
devscript that starts compilation in
watchmode—file changes will start a new build.
Finally, link the library in the project you would like to test the changes:
# 4. Link the library by name to use the local copy yarn link vite
Just as in the previous section, it’s important to restart the process you intend to debug after making changes.
Why is it necessary to restart? 🤔
Most processes will load the required libraries into memory, and then use these cached versions during their entire running time.
Restarting the relevant process, such as the Vite.js development server, ensures the updated version of the library is loaded.
Additional Resources 📖
I hope this summary has been useful! A similar guide for Ruby is available 😃
Please refer to the following documentation for more information: