Node.js – JavaScript Runtime for Server-Side Applications

4.9 Stars
Version 20.10
30 MB

What is Node.js?

Node.js is an open-source, cross-platform JavaScript runtime environment that executes JavaScript code outside a web browser. Built on Chrome’s V8 JavaScript engine, Node.js enables developers to use JavaScript for server-side scripting, creating dynamic web applications with a unified language across front-end and back-end development.

Since its creation by Ryan Dahl in 2009, Node.js has revolutionized web development by bringing JavaScript to the server. Its event-driven, non-blocking I/O model makes it lightweight and efficient, particularly well-suited for data-intensive real-time applications that run across distributed devices.

Node.js powers some of the world’s largest platforms including Netflix, PayPal, LinkedIn, Uber, and NASA. Its vast ecosystem of packages through npm (Node Package Manager) provides developers with tools for virtually any application requirement, from web frameworks to machine learning libraries.

Key Features and Capabilities

Asynchronous and Event-Driven

Node.js uses an event-driven, non-blocking I/O model that handles concurrent connections efficiently. Unlike traditional threaded models, Node.js operates on a single thread with an event loop, making it capable of handling thousands of concurrent connections with minimal overhead.

V8 JavaScript Engine

Node.js runs on Google’s V8 engine, which compiles JavaScript directly to native machine code. This provides exceptional performance and continuous improvements as V8 evolves. The engine supports modern ECMAScript features, enabling developers to use the latest JavaScript syntax.

NPM Ecosystem

The Node Package Manager (npm) hosts over 2 million packages, making it the largest software registry in the world. This extensive ecosystem accelerates development by providing pre-built solutions for common challenges, from utility functions to complete frameworks.

Cross-Platform

Node.js applications run identically on Windows, macOS, and Linux. This cross-platform compatibility extends to building desktop applications with Electron, mobile apps with React Native, and IoT devices, maximizing code reuse across platforms.

Built-in Modules

Node.js includes essential modules for file system operations, networking, streams, cryptography, and more. These core modules provide foundational capabilities without external dependencies.

System Requirements

Hardware Requirements

Node.js runs on minimal hardware—any system capable of running a modern operating system can run Node.js. Production applications typically require resources proportional to their workload, with memory being the primary consideration for concurrent connection handling.

Operating System Support

Node.js supports Windows 10/Server 2016+, macOS 10.15+, and various Linux distributions including Ubuntu, Debian, RHEL, CentOS, and Alpine. ARM platforms including Raspberry Pi are also supported.

Installation Guide

Installing on Ubuntu/Debian

# Using NodeSource repository (recommended)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# Verify installation
node --version
npm --version

# Using apt (may be older version)
sudo apt update
sudo apt install nodejs npm

# Using nvm (Node Version Manager) - recommended for development
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install 20
nvm use 20

Installing on RHEL/CentOS

# Using NodeSource repository
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo dnf install -y nodejs

# Using dnf (may be older version)
sudo dnf module enable nodejs:20
sudo dnf install nodejs

Installing on macOS

# Using Homebrew
brew install node

# Using nvm (recommended)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
nvm install 20
nvm use 20

# Download installer from nodejs.org

Installing on Windows

# Download installer from nodejs.org
# Run installer with default options

# Using Chocolatey
choco install nodejs

# Using Winget
winget install OpenJS.NodeJS

# Using nvm-windows
# Download from github.com/coreybutler/nvm-windows
nvm install 20
nvm use 20

Using Docker

# Pull official Node.js image
docker pull node:20

# Run interactive container
docker run -it node:20 node

# Run application
docker run -v $(pwd):/app -w /app node:20 npm start

# Dockerfile example
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

NPM Basics

Package Management Commands

# Initialize new project
npm init
npm init -y  # Accept defaults

# Install dependencies
npm install express
npm install -D jest  # Dev dependency
npm install -g nodemon  # Global install

# Install all dependencies from package.json
npm install
npm ci  # Clean install (for CI/production)

# Update packages
npm update
npm update express

# Remove package
npm uninstall express

# List installed packages
npm list
npm list --depth=0  # Top-level only
npm list -g  # Global packages

# Check for outdated packages
npm outdated

# Audit security vulnerabilities
npm audit
npm audit fix

# Run scripts
npm run start
npm run test
npm run build

# View package info
npm info express
npm view express versions

package.json Structure

{
  "name": "my-app",
  "version": "1.0.0",
  "description": "My Node.js application",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js",
    "test": "jest",
    "build": "webpack --mode production",
    "lint": "eslint ."
  },
  "dependencies": {
    "express": "^4.18.2",
    "mongoose": "^8.0.0"
  },
  "devDependencies": {
    "jest": "^29.7.0",
    "nodemon": "^3.0.0",
    "eslint": "^8.50.0"
  },
  "engines": {
    "node": ">=18.0.0"
  },
  "keywords": ["node", "express", "api"],
  "author": "Your Name",
  "license": "MIT"
}

Core Node.js Concepts

Event Loop

// Understanding the event loop
console.log('1. Synchronous');

setTimeout(() => {
  console.log('4. Timeout callback');
}, 0);

Promise.resolve().then(() => {
  console.log('3. Promise microtask');
});

console.log('2. Synchronous');

// Output order: 1, 2, 3, 4

File System Operations

import { readFile, writeFile, mkdir, readdir } from 'fs/promises';
import { existsSync } from 'fs';

// Read file
const content = await readFile('file.txt', 'utf-8');
console.log(content);

// Write file
await writeFile('output.txt', 'Hello, World!');

// Check if file exists
if (existsSync('file.txt')) {
  console.log('File exists');
}

// Create directory
await mkdir('new-folder', { recursive: true });

// Read directory
const files = await readdir('.');
console.log(files);

// Read JSON file
const config = JSON.parse(
  await readFile('config.json', 'utf-8')
);

HTTP Server

import http from 'http';

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({
    message: 'Hello, World!',
    path: req.url,
    method: req.method
  }));
});

server.listen(3000, () => {
  console.log('Server running at http://localhost:3000');
});

Streams

import { createReadStream, createWriteStream } from 'fs';
import { pipeline } from 'stream/promises';
import { createGzip } from 'zlib';

// Read large file with stream
const readStream = createReadStream('large-file.txt');
readStream.on('data', (chunk) => {
  console.log(`Received ${chunk.length} bytes`);
});

// Pipe to compress file
await pipeline(
  createReadStream('input.txt'),
  createGzip(),
  createWriteStream('input.txt.gz')
);

// Transform stream
import { Transform } from 'stream';

const uppercase = new Transform({
  transform(chunk, encoding, callback) {
    this.push(chunk.toString().toUpperCase());
    callback();
  }
});

Building REST APIs with Express

Basic Express Application

import express from 'express';

const app = express();

// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Logging middleware
app.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next();
});

// Routes
app.get('/', (req, res) => {
  res.json({ message: 'Welcome to the API' });
});

app.get('/users', (req, res) => {
  res.json([
    { id: 1, name: 'John' },
    { id: 2, name: 'Jane' }
  ]);
});

app.get('/users/:id', (req, res) => {
  const { id } = req.params;
  res.json({ id, name: `User ${id}` });
});

app.post('/users', (req, res) => {
  const { name, email } = req.body;
  res.status(201).json({ id: 3, name, email });
});

// Error handling
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Something went wrong!' });
});

// Start server
app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Router Organization

// routes/users.js
import { Router } from 'express';

const router = Router();

router.get('/', (req, res) => {
  res.json({ users: [] });
});

router.post('/', (req, res) => {
  res.status(201).json({ user: req.body });
});

router.get('/:id', (req, res) => {
  res.json({ user: { id: req.params.id } });
});

export default router;

// app.js
import userRoutes from './routes/users.js';
app.use('/api/users', userRoutes);

Asynchronous Patterns

Promises and Async/Await

// Promise-based function
function fetchUser(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id > 0) {
        resolve({ id, name: 'User' });
      } else {
        reject(new Error('Invalid ID'));
      }
    }, 100);
  });
}

// Async/await usage
async function getUser(id) {
  try {
    const user = await fetchUser(id);
    console.log(user);
    return user;
  } catch (error) {
    console.error('Error:', error.message);
  }
}

// Parallel execution
const [user1, user2] = await Promise.all([
  fetchUser(1),
  fetchUser(2)
]);

// Promise.allSettled for handling mixed results
const results = await Promise.allSettled([
  fetchUser(1),
  fetchUser(-1),
  fetchUser(3)
]);

results.forEach((result) => {
  if (result.status === 'fulfilled') {
    console.log('Success:', result.value);
  } else {
    console.log('Failed:', result.reason);
  }
});

Environment Variables

Configuration Management

# .env file
NODE_ENV=development
PORT=3000
DATABASE_URL=mongodb://localhost:27017/myapp
JWT_SECRET=your-secret-key
API_KEY=your-api-key
// Using dotenv
import 'dotenv/config';

// Or
import dotenv from 'dotenv';
dotenv.config();

// Access variables
const port = process.env.PORT || 3000;
const dbUrl = process.env.DATABASE_URL;
const isProduction = process.env.NODE_ENV === 'production';

// Config module pattern
// config/index.js
export default {
  port: parseInt(process.env.PORT, 10) || 3000,
  database: {
    url: process.env.DATABASE_URL,
    name: process.env.DB_NAME
  },
  jwt: {
    secret: process.env.JWT_SECRET,
    expiresIn: '24h'
  }
};

Testing with Jest

Unit Testing

// math.js
export function add(a, b) {
  return a + b;
}

export function divide(a, b) {
  if (b === 0) throw new Error('Cannot divide by zero');
  return a / b;
}

// math.test.js
import { add, divide } from './math.js';

describe('Math functions', () => {
  test('adds 1 + 2 to equal 3', () => {
    expect(add(1, 2)).toBe(3);
  });

  test('divides 10 / 2 to equal 5', () => {
    expect(divide(10, 2)).toBe(5);
  });

  test('throws error when dividing by zero', () => {
    expect(() => divide(10, 0)).toThrow('Cannot divide by zero');
  });
});

// API testing
import request from 'supertest';
import app from './app.js';

describe('GET /api/users', () => {
  it('responds with json array', async () => {
    const response = await request(app)
      .get('/api/users')
      .expect('Content-Type', /json/)
      .expect(200);
    
    expect(Array.isArray(response.body)).toBe(true);
  });
});

Debugging

Debugging Techniques

# Start with inspector
node --inspect server.js
node --inspect-brk server.js  # Break on first line

# Debug with Chrome DevTools
# Open chrome://inspect

# Using debugger statement
function calculate(x) {
  debugger;  // Pause here
  return x * 2;
}

# Console debugging
console.log('Value:', variable);
console.dir(object, { depth: null });
console.table(array);
console.time('operation');
// ... code
console.timeEnd('operation');

Process Management

Using PM2

# Install PM2
npm install -g pm2

# Start application
pm2 start server.js
pm2 start server.js --name "api"
pm2 start server.js -i max  # Cluster mode

# Manage processes
pm2 list
pm2 stop api
pm2 restart api
pm2 delete api

# Logs
pm2 logs
pm2 logs api

# Monitoring
pm2 monit

# Generate startup script
pm2 startup
pm2 save

# Ecosystem file
// ecosystem.config.cjs
module.exports = {
  apps: [{
    name: 'api',
    script: 'server.js',
    instances: 'max',
    exec_mode: 'cluster',
    env: {
      NODE_ENV: 'development'
    },
    env_production: {
      NODE_ENV: 'production'
    }
  }]
};

Conclusion

Node.js has transformed JavaScript from a browser-only language into a versatile platform for building everything from APIs to desktop applications. Its non-blocking architecture, massive ecosystem, and unified JavaScript development experience make it an excellent choice for modern application development.

Whether building microservices, real-time applications, or command-line tools, Node.js provides the performance and flexibility needed for today’s demanding applications.

Developer: OpenJS Foundation

Download Options

Download Node.js – JavaScript Runtime for Server-Side Applications

Version 20.10

File Size: 30 MB

Download Now
Safe & Secure

Verified and scanned for viruses

Regular Updates

Always get the latest version

24/7 Support

Help available when you need it