Node.js Development

Node.js Development Guide

Node.js is a JavaScript runtime built on Chrome’s V8 JavaScript engine that allows you to run JavaScript on the server side. This guide covers essential concepts, tools, and best practices for Node.js development.

Table of Contents

Version Management

Node Version Manager (nvm)

Node Version Manager allows you to install and switch between multiple Node.js versions.

Installation

# Using curl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

# Using wget
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

Basic Commands

nvm --version                    # Check nvm version
nvm list                         # List installed versions
nvm list-remote                  # List available versions
nvm install node                 # Install latest Node.js
nvm install 18.17.0             # Install specific version
nvm use 18.17.0                 # Switch to specific version
nvm use node                    # Use latest version
nvm alias default 18.17.0       # Set default version
nvm current                     # Show current version
nvm which node                  # Show path to current version

Project-specific Node Version

# Create .nvmrc file in project root
echo "18.17.0" > .nvmrc

# Use version specified in .nvmrc
nvm use

# Install version if not available
nvm install

Alternative Version Managers

fnm (Fast Node Manager)

# Installation
curl -fsSL https://fnm.vercel.app/install | bash

# Usage
fnm install 18.17.0
fnm use 18.17.0
fnm default 18.17.0
fnm list

Volta

# Installation
curl https://get.volta.sh | bash

# Usage
volta install node@18.17.0
volta pin node@18.17.0

NPM Package Manager

NPM (Node Package Manager) is the default package manager for Node.js applications.

Project Initialization

npm init                    # Interactive setup
npm init -y                # Skip prompts with defaults
npm create vite@latest     # Create Vite project
npm create react-app my-app # Create React app
npm create next-app@latest # Create Next.js app

Package Management

npm install                    # Install all dependencies
npm install <package>          # Install package
npm install <package> --save-dev  # Install as dev dependency
npm install <package> --global    # Install globally
npm install <package>@<version>   # Install specific version
npm uninstall <package>       # Remove package
npm update                    # Update all packages
npm update <package>          # Update specific package
npm outdated                  # Check for outdated packages

Development Workflow

npm run dev      # Start development server
npm run build    # Build for production
npm run start    # Start production server
npm run test     # Run tests
npm run lint     # Run linter
npm run preview  # Preview production build

Package Information

npm list                    # List installed packages
npm list --depth=0          # List top-level packages only
npm list --global           # List globally installed packages
npm info <package>          # Show package information
npm search <package>        # Search for packages
npm view <package> versions # Show available versions

Cache Management

npm cache clean --force  # Clear cache
npm cache verify         # Verify cache integrity

Publishing Packages

npm login                 # Login to npm registry
npm publish               # Publish package
npm version patch|minor|major  # Bump version
npm unpublish <package>@<version>  # Unpublish package

Configuration

npm config list                    # Show all config
npm config get registry           # Get registry URL
npm config set registry https://registry.npmjs.org/  # Set registry
npm config delete <key>           # Delete config key

Scripts

npm run <script-name>      # Run custom script
npm run-script <script-name>  # Alternative syntax

Useful Flags

  • --save-dev or -D: Install as development dependency
  • --global or -g: Install globally
  • --force or -f: Force operation
  • --production: Skip dev dependencies during install
  • --dry-run: Show what would be done without executing
  • --silent: Suppress npm output

Express.js Framework

Express.js is a minimal and flexible Node.js web application framework.

Basic Setup

npm install express --save
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

MERN Stack

MERN = MongoDB + Express.js + React + Node.js

Express.js serves as the backend API server in the MERN stack, handling HTTP requests and responses between the React frontend and MongoDB database.

Package.json Configuration

The package.json file contains metadata about your Node.js project and defines dependencies and scripts.

Basic Structure

{
  "name": "my-app",
  "version": "1.0.0",
  "description": "My Node.js application",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    "test": "jest",
    "build": "webpack --mode production",
    "lint": "eslint .",
    "lint:fix": "eslint . --fix"
  },
  "keywords": ["node", "javascript"],
  "author": "Your Name <email@example.com>",
  "license": "MIT"
}

Dependencies

{
  "dependencies": {
    "express": "^4.18.2",
    "lodash": "~4.17.21"
  },
  "devDependencies": {
    "nodemon": "^2.0.20",
    "jest": "^29.3.1",
    "eslint": "^8.31.0"
  },
  "peerDependencies": {
    "react": ">=16.8.0"
  },
  "optionalDependencies": {
    "fsevents": "^2.3.2"
  }
}

Scripts Examples

{
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon --watch src server.js",
    "test": "jest --coverage",
    "test:watch": "jest --watch",
    "build": "webpack --mode production",
    "build:dev": "webpack --mode development",
    "lint": "eslint src/",
    "lint:fix": "eslint src/ --fix",
    "format": "prettier --write src/",
    "clean": "rm -rf dist/",
    "prebuild": "npm run clean",
    "postinstall": "npm run build",
    "serve": "serve -s dist/",
    "docker:build": "docker build -t my-app .",
    "docker:run": "docker run -p 3000:3000 my-app"
  }
}

Configuration Fields

{
  "engines": {
    "node": ">=16.0.0",
    "npm": ">=8.0.0"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ],
  "repository": {
    "type": "git",
    "url": "https://github.com/username/repo.git"
  },
  "bugs": {
    "url": "https://github.com/username/repo/issues"
  },
  "homepage": "https://github.com/username/repo#readme"
}

Module Configuration

{
  "type": "module",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    },
    "./package.json": "./package.json"
  },
  "files": [
    "dist/",
    "README.md",
    "LICENSE"
  ]
}

Version Ranges

  • ^1.2.3: Compatible with 1.2.3, allows minor and patch updates
  • ~1.2.3: Compatible with 1.2.3, allows only patch updates
  • >=1.2.3: Version 1.2.3 or higher
  • <1.2.3: Version lower than 1.2.3
  • 1.2.3: Exact version 1.2.3

Debugging and Development

Node Inspector

node --inspect app.js              # Start with inspector
node --inspect-brk app.js          # Start with breakpoint at first line
node --inspect=0.0.0.0:9229 app.js # Bind to all interfaces

Chrome DevTools

  1. Run node --inspect app.js
  2. Open Chrome and navigate to chrome://inspect
  3. Click “Open dedicated DevTools for Node”

VS Code Debugging

Create .vscode/launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Program",
      "program": "${workspaceFolder}/app.js",
      "console": "integratedTerminal"
    },
    {
      "type": "node",
      "request": "attach",
      "name": "Attach to Process",
      "port": 9229
    }
  ]
}

Environment Variables

NODE_ENV=development node app.js
DEBUG=* node app.js
DEBUG=app:* node app.js

.env Files

NODE_ENV=development
PORT=3000
DATABASE_URL=mongodb://localhost:27017/myapp

Load with dotenv:

require('dotenv').config();

Performance Profiling

node --prof app.js
node --prof-process isolate-*.log > profile.txt

Memory Debugging

node --inspect --max-old-space-size=4096 app.js
node --trace-gc app.js

Logging

Winston

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

Debug Module

const debug = require('debug')('app:server');
debug('Starting server on port %d', port);

Testing

Jest

npm test
npm test -- --watch
npm test -- --coverage

Mocha

npx mocha test/
npx mocha test/ --watch
npx mocha test/ --reporter spec

Common Debugging Patterns

// Console debugging
console.log('Debug:', variable);
console.error('Error:', error);
console.time('operation');
console.timeEnd('operation');

// Breakpoint debugging
debugger;

// Process debugging
process.on('uncaughtException', (err) => {
  console.error('Uncaught Exception:', err);
  process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});

Performance Monitoring

// Process metrics
console.log('Memory usage:', process.memoryUsage());
console.log('CPU usage:', process.cpuUsage());

// Event loop monitoring
const { performance } = require('perf_hooks');
const start = performance.now();
// ... code to measure
const end = performance.now();
console.log(`Execution time: ${end - start} ms`);

Vite Build Tool

Vite is a fast build tool and development server for modern web projects.

Project Setup

npm create vite@latest my-app
cd my-app
npm install
npm run dev

React Template

npm create vite@latest my-app --template react
cd my-app
npm install
npm run dev

Project Structure

my-app/
├── index.html
├── vite.config.js
├── package.json
├── src/
│   ├── main.jsx
│   └── App.jsx
└── public/

Next.js Framework

Next.js is a React framework for production with built-in SSR, SSG, and API routes.

Project Setup

npx create-next-app@latest my-nextjs-app
cd my-nextjs-app
npm run dev

Access at: http://localhost:3000

Nodemon Development Tool

Nodemon automatically restarts your Node.js application when files change.

Installation and Usage

npm install -g nodemon
nodemon app.js
nodemon --watch src app.js
nodemon --ignore node_modules/ app.js

Configuration (nodemon.json)

{
  "watch": ["src"],
  "ext": "js,json",
  "ignore": ["node_modules/", "dist/"],
  "exec": "node app.js"
}

Nodemon is essential for development workflows, providing hot reloading without manual server restarts.

Additional Resources