How to Debug a Node.js Application: Tips, Tricks and Tools

.gitignore 3D accessibility accessible headings ad banner ad revenue ad revenues adobe XD Advanced advanced-css-tools advanced-css-tutorials AdvancedCSS AdvancedCSS-hub agency Agile Agile Development ai Ajax Alex Skill Kit Alexa Alexa skill AlexW Amazon Alexa amazon developer analytics Angelap angular AngularJS Animation anime.js ANN api apollo Appsflyer architecture ARIA aria attributes array methods artificial neural network Async async components AurelioD automation Avocode AWS AWS Lambda axios b2b b2c baas background background eraser tool Banner banner ad Bannersnack bash bash commands bawmedia bem bitcoin black friday Blogs bootstrap bot browser testing Browsers build process bundler Business business success C Canvas & SVG career Career Advancement CDN Chakra UI charting chat app chatbots ChatKit chrome chrome developer tools chrome extension chrome extensions chromium ciphering cli cli tools climate climate action clip-path clojure cloning Cloud cloud hosting CloudFlare Cloudways cms CNN code challenge ColinI collaboration collaboration tools color contrast committing changes compiler components conflicts const assertions constructs content content delivery network content organization context api convoluted neural network create react app cron job cross browser testing cross platform development cross-browser cryptocurrencies cryptocurrency CSS CSS Animations CSS Architecture css blur css challenge css framework css frameworks css grid css layout css master css modules CSS print css rem css typography CSS-in-JS CSS3 css3 transforms cssbattle.dev D3.js data science data visualization database databases debugging decoupled cms deep linking delay Design Design & UX design career design handoff Detox dev environment dev job developer job developer tools DevOps devtools diagnostic analytics digit recognition digital agency digitalocean Discord discounts django Docker Docker Containers drag & drop dropzone.js E-commerce ECMAScript edge computing editor elastic em units employment encryption end-to-end testing energy energy usage Entrepreneur Entrepreneurship environment erasing backgrounds es6 ES6 classes eslint Expo Express FaaS face detection face recognition fast wordpress themes Feathers Feathers.js figma flask flatfile flexible wordpress theme forking form validation forms tutorial framework Frameworks freelancing functional programming functions gatsby generators geolocation get organized getting a job GIPHY git git branching git lfs git merging gitCS github github API Google Photos GraphCMS graphing graphql Growth Grunt grunt-watch Gulp hapi haskell headless CMS hide and show page elements hooks hosting HTML HTML & CSS html preprocessor HTML5 HTML5 Dev Center HTML5 Tutorials & Articles https://www.sitepoint.com/windows-linux-subsystem-2-windows-terminal IAAS IDE Illustration image optimization immutability Interview ionic IP2Location ipdata jade jamesh JavaScript javascript framework javascript frameworks javascript tooling Jest job job hunting job interview jobs joelf jQuery jQuery functions jquery get url params jquery string functions jQuery.each() jQuery.each() Array Example jquery4u js js framework JS tooling Keras keycdn kubernetes lambdatest launch checklist Layout learn javascript learn typescript learn-advanced-css learn-modernjs Learn-Node-JS learn-vue Let's Encrypt Lift linux linux containers location tracking LouisL machine learning Managed managed hosting managing remotes mariap marvel MATLAB MBaaS mekanism mental health merging mind map mind mapping mindmapping Mobile mobile attribution Mobile Design modern css modernjs modernjs-hub modernjs-tools modernjs-tutorials modules moment.js monday mongodb MTCNN multi-threading mvc mysql MySQL install natural language processing Navigation navigation library nest Next.js nginx nilsonj no-code node node version manager node-hub Node-JS-Tools Node-JS-Tutorials node-mysql module Node.js NodeGui nodejs noops nosql npm nvm objects octobercms Offers on-premise online publishing organize organize files PaaS Package Management package manager pair programming pairing patrickc pause Percy Performance Photography & Imagery Photoshop Photoshop Tutorials & Articles pip pipeline portfolio portfolio builders preprocessors prettier print styles Prisma Private Class Fields product design Productivity productivity tips Profitability Programming programming job projects PubNub Pug Puppeteer Pusher python python framework python interview python job Quasar query strings quick-tip quiz quote builders r Raw JavaScript React react components React Hooks React Hooks Form React native React-Tools reactive Reactive Programming reactive web apps read offline Reat native elements Recurring Payments recursive types RedBox redux rem units remote job remote teams remote work remote work tips remote working removing backgrounds resilient Resources responsive REST restful api Review SaaS sampling sass Scss self sencha Sequelize server server-side serverless serverless computing shared hosting sharing state sharpen shell shell commands side project siteground sketch slashdata sleep Software software commits sorting sourcetree specifications speech recognition speech recognition api sponsored sql ssl Stack Overflow Startups state state management static module bundler StudioWorks Styled Components styling React components survey sustainability svelte sympli Tailwind task runner telegram bots Template engine Testing text to speech Themes Tic Tac Toe Tinder toggle Tolerance tooling tooling anxiety tools Tools & Libraries transformations TypeScript typescript skills Ubuntu UI UI Design Usability user experience user research UX ux issues vanilla javascript VGGFace2 virtual machine visual testing voice recognition vps vue Vue CLI vue dev environment vue-hub vue-tutorials vue.js vuetify vuex wait WatermelonDB Web Web Design web hosting Web Hosting & Domains Web standards web workers webpack website builders website performance WebSockets windows windows 10 home Windows Subsystem for Linux Windows Terminal wix women women in tech WordPress wordpress plugin wordpress themes WordPress theming work workers workflow working remotely workplaces WPEngine WSL WSL2 YellowBox Zeplin zsh zsh command zsh plugin zsh tools

Two figures in protective suits with weapons, battling a giant spider-like bug

Software development is complex and, at some point, your Node.js application will fail. If you’re lucky, your code will crash with an obvious error message. If you’re unlucky, your application will carry on regardless but not generate the results you expect. If you’re really unlucky, everything will work fine until the first user discovers a catastrophic disk-wiping bug.

What is Debugging?

Debugging is the black art of fixing software defects. Fixing a bug is often easy — a corrected character or additional line of code solves the problem. Finding that bug is another matter, and developers can spend many unhappy hours trying to locate the source of an issue. Fortunately, Node.js has some great tools to help trace errors.

Terminology

Debugging has its own selection of obscure jargon, including the following:

Term Explanation
breakpoint the point at which a debugger stops a program so its state can be inspected
debugger a tool which offers debugging facilities such as running code line by line to inspect internal variable states
feature as in the claim: “it’s not a bug, it’s a feature”. All developers say it at some point during their career
frequency how often or under what conditions a bug will occur
it doesn’t work the most-often made but least useful bug report
log point an instruction to a debugger to show the value of a variable at a point during execution
logging output of runtime information to the console or a file
logic error the program works but doesn’t act as intended
priority where a bug is allocated on a list of planned updates
race condition hard-to-trace bugs dependent the sequence or timing of uncontrollable events
refactoring rewriting code to help readability and maintenance
regression re-emergence of a previously fixed bug perhaps owing to other updates
related a bug which is similar or related to another
reproduce the steps required to cause the error
RTFM error user incompetence disguised as a bug report, typically followed by a response to “Read The Flipping Manual”
step into when running code line by line in a debugger, step into the function being called
step out when running line by line, complete execution of the current function and return to the calling code
step over when running line by line, complete execution of a command without stepping into a function it calls
severity the impact of a bug on system. For example, data loss would normally be considered more problematic than a UI issue unless the frequency of occurrence is very low
stack trace the historical list of all functions called before the error occurred
syntax error typographical errors, such as console.lug()
user error an error caused by a user rather than the application, but may still incur an update depending on that person’s seniority
watch a variable to examine during debugger execution
watchpoint similar to a breakpoint, except the program is stopped when a variable is set to a specific value

How to Avoid Bugs

Bugs can often be prevented before you test your application …

Use a Good Code Editor

A good code editor will offer numerous features including line numbering, auto-completion, color-coding, bracket matching, formatting, auto-indentation, variable renaming, snippet reuse, object inspection, function navigation, parameter prompts, refactoring, unreachable code detection, suggestions, type checking, and more.

Node.js devs are spoiled for choice with free editors such as VS Code, Atom, and Brackets, as well as plenty of commercial alternatives.

Use a Code Linter

A linter can report code faults such as syntax errors, poor indentation, undeclared variables, and mismatching brackets before you save and test your code. The popular options for JavaScript and Node.js include ESLint, JSLint, and JSHint.

These are often installed as global Node.js modules so you can run checks from the command line:

eslint myfile.js

However, most linters have code editor plugins, such as ESLint for VS Code and linter-eslint for Atom which check your code as you type:

ESLint for VS Code

Use Source Control

A source control system such as Git can help safe-guard your code and manage revisions. It becomes easier to discover where and when a bug was introduced and who should receive the blame! Online repositories such as GitHub and Bitbucket offer free space and management tools.

Adopt an Issue-tracking System

Does a bug exist if no one knows about it? An issue-tracking system is used to report bugs, find duplicates, document reproduction steps, determine severity, calculate priorities, assign developers, record discussions, and track progress of any fixes.

Online source repositories often offer basic issue tracking, but dedicated solutions may be appropriate for larger teams and projects.

Use Test-driven Development

Test-driven Development (TDD) is a development process which encourages developers to write code which tests the operation of a function before it’s written — for example, is X returned when function Y is passed input Z.

Tests can be run as the code is developed to prove a function works and spot any issues as further changes are made. That said, your tests could have bugs too …

Step Away

It’s tempting to stay up all night in a futile attempt to locate the source of a nasty bug. Don’t. Step away and do something else. Your brain will subconsciously work on the problem and wake you at 4am with a solution. Even if that doesn’t happen, fresh eyes will spot that obvious missing semicolon.

Node.js Debugging: Environment Variables

Environment variables that are set within the host operating system can be used to control Node.js application settings. The most common is NODE_ENV, which is typically set to development when debugging.

Environment variables can be set on Linux/macOS:

NODE_ENV=development

Windows cmd:

set NODE_ENV=development

Or Windows Powershell:

$env:NODE_ENV="development"

Internally, an application will enable further debugging features and messages. For example:

// is NODE_ENV set to "development"?
const DEVMODE = (process.env.NODE_ENV === 'development');

if (DEVMODE) {
  console.log('application started in development mode on port ${PORT}');
}

NODE_DEBUG enables debugging messages using the Node.js util.debuglog (see below), but also consult the documentation of your primary modules and frameworks to discover further options.

Note that environment variables can also be saved to a .env file. For example:

NODE_ENV=development
NODE_LOG=./log/debug.log
SERVER_PORT=3000
DB_HOST=localhost
DB_NAME=mydatabase

Then loaded using the dotenv module:

require('dotenv').config();

Node.js Debugging: Command Line Options

Various command-line options can be passed to the node runtime when launching an application. One of the most useful is --trace-warnings, which outputs stack traces for process warnings (including deprecations).

Any number of options can be set, including:

  • --enable-source-maps: enable source maps (experimental)
  • --throw-deprecation: throw errors when deprecated features are used
  • --inspect: activate the V8 inspector (see below)

By way of an example, let’s try to log the crypto module’s DEFAULT_ENCODING property, which was deprecated in Node v10:

const crypto = require('crypto');

function bar() {
  console.log(crypto.DEFAULT_ENCODING);
}

function foo(){
  bar();
}

foo();

Now run this with the following:

node index.js

We’ll then see this:

buffer
(node:7405) [DEP0091] DeprecationWarning: crypto.DEFAULT_ENCODING is deprecated.

However, we can also do this:

node --trace-warnings index.js

That produces the following:

buffer
(node:7502) [DEP0091] DeprecationWarning: crypto.DEFAULT_ENCODING is deprecated.
    at bar (/home/Desktop/index.js:4:22)
    at foo (/home/Desktop/index.js:8:3)
    at Object.<anonymous> (/home/Desktop/index.js:11:1)
    at Module._compile (internal/modules/cjs/loader.js:1151:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1171:10)
    at Module.load (internal/modules/cjs/loader.js:1000:32)
    at Function.Module._load (internal/modules/cjs/loader.js:899:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47

This tells us that the deprecation warning comes from the code in line 4 (the console.log statement), which was executed when the bar function ran. The bar function was called by the foo function on line 8 and the foo function was called on line 11 of our script.

Note that the same options can also be passed to nodemon.

Console Debugging

One of the easiest ways to debug an application is to output values to the console during execution:

console.log( myVariable );

Few developers delve beyond this humble debugging command, but they’re missing out on many more possibilities, including these:

console method description
.log(msg) output a message to the console
.dir(obj,opt) uses util.inspect to pretty-print objects and properties
.table(obj) outputs arrays of objects in tabular format
.error(msg) output an error message
.count(label) a named counter reporting the number of times the line has been executed
.countReset[label] resets a named counter
.group(label) indents a group of log messages
.groupEnd(label) ends the indented group
.time(label) starts a timer to calculate the duration of an operation
.timeLog([label] reports the elapsed time since the timer started
.timeEnd(label) stops the timer and reports the total duration
.trace() outputs a stack trace (a list of all calling functions)
.clear() clear the console

console.log() accepts a list of comma-separated values. For example:

let x = 123;
console.log('x:', x);
// x: 123

However, ES6 destructuring can offer similar output with less typing effort:

console.log({x});
// { x: 123 }

Larger objects can be output as a condensed string using this:

console.log( JSON.stringify(obj) );

util.inspect will format objects for easier reading, but console.dir() does the hard work for you.

The post How to Debug a Node.js Application: Tips, Tricks and Tools appeared first on SitePoint.

Original Article

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.