A good debugging environment is essential for speed of development. A good debugging environment includes:
- Breakpoints for frontend and backend
- Variable inspection
- Live updates or auto-restart on code changes
- Properly implemented source-maps
Since the inception of Node.js and especially ES6 features, it has been difficult and sometimes nearly impossible to get all four items above in one place. There seems to always be some problem with connecting a debugger to the Node.js process or the source-maps not working properly and breakpoints are interpreted as on the wrong lines. It's especially frustrating if the code you set breakpoints on is the generated code and not the original file. It is not surprising that a lot of engineers use console.log
for most of their debugging.
Before I even started writing any part of my blog code, I made sure that all four items above were working.
Debugging Strapi.js
It was a nightmare getting VSCode to debug my Strapi.js process and connect to it.
One problem with Node.js right now is that there are a plethora of utilities to start your Javascript application... and each one requires a slightly different method to begin debugging.
For example, you can start Strapi.js in all of the following ways:
yarn start
(with package.json run scripts)npm run start
(with package.json run scripts)strapi develop
node ./node_modules/strapi/bin/strapi.js develop
- Create a root
index.js
and importstrapi.js
and call develop manually
While the flexibility is nice, it is also a nightmare knowing how to connect a debugger to your application. Hopefully I can clear this up a little bit in this post.
Debugging Node.js
Before continuing, it might be good to read through the Node.js Debugging Guide.
It is important to realize that Node.js by default is a single process. This will become important later when we start debugging strapi. As a result, if you have a simple index.js file like this:
// index.js
console.log('hello world');
You can start it and enable debugging by doing the following:
$ node --inspect index.js
This does not actually do the debugging itself, it simply opens up a port so that another process can watch variables, set breakpoints, and step through the code. In other words, by running this you simply allow another process to control the debugging of your index.js
. That other program could be something like VSCode. By default the debugging process is opened up on localhost on port 9229. So VSCode would need to connect to port 9229 in order to debug your script.
So then, the above is identical to:
$ node --inspect=0.0.0.0:9229 index.js
Typically, however, the recommendation given for frameworks like Strapi is that you use npm
or yarn
to start your application.
How do you debug it then? You can edit the default provided package.json
development command. For most applications,that would look like this:
...
"scripts": {
"develop: "node.js --inspect index.js"
}
...
With Strapi.js, however, the default package.json
script is this:
...
"scripts": {
"develop: "strapi develop"
}
...
How do you debug the strapi
command when it does not have an --inspect
option?
Debugging Strapi
In order to debug Strapi, you need to call the script directly with the Node.js command instead of relying on the launcher script, like this:
$ node --inspect=0.0.0.0:9229 ./node_modules/strapi/bin/strapi.js develop
I fought this for hours and hours (probably 6-8) with VSCode and this was the result that I eventually settled on.
Keep in mind, this only starts Strapi in development mode with debugging enabled. Now I needed to set up VSCode.
Connecting VSCode Debugger
VSCode has a unique launch configuration. In order to setup VSCode to launch processes, you need to create a launch.json
:
# in your project root folder
/.vscode/launch.json
My launch JSON ended up looking like this to launch Strapi.js:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"trace": true,
"outputCapture": "std",
"name": "Backend",
"runtimeExecutable": "/Users/joshjung/.nvm/versions/node/v10.16.0/bin/npm",
"runtimeArgs": ["run", "debug"],
"cwd": "/Users/joshjung/dev/joshoncode/backend",
"localRoot": "/Users/joshjung/dev/joshoncode/backend",
"remoteRoot": "/Users/joshjung/dev/joshoncode/backend",
"port": 9229
}
]
}
The settings I have above were chosen after massive amounts of fighting with things. For reference I am using VSCode 1.43.2
.
Remember that I mentioned that Node.js spawns a single process by default. Well, I think I ran into issues getting the console output to work right for Strapi because it appears that Strapi might spawn other processes and VSCode was not seeing that output. The outputCapture
and trace
options were chosen because I ran into issues where the standard output (e.g. console.log
) of the application was not always being captured.
Debugging Nuxt.js
Debugging Nuxt.js was really straightforward. I believe the only change I had to make was in the build
block of nuxt.config.js
in the root folder:
...
/*
** Build configuration
*/
build: {
postcss: {
preset: {
features: {
customProperties: false
}
}
},
/*
** You can extend webpack config here
*/
extend (config) {
config.devtool = '#source-map' // I added this to
}
},
...
More information on this can be found in this Stack Overflow issue from last year.
All of my Nuxt.js debugging is done in Chrome or Firefox by using the Developer Tools and going to the Sources tab and searching for the file I want to debug by using Ctrl-Shift-P and typing in the filename (e.g. "MyComponent.vue"
). Then I can easily set breakpoints in the original code, thanks to the source maps.
Conclusion
While Nuxt.js was easy to debug, Strapi.js gave me some trouble mostly do to the fact I had to do some digging online to work around some issues both with the Node.js debugger and VSCode. Hopefully this guide helps someone out!