From core concepts to production deployment. Your comprehensive guide to server-side JavaScript.
Node.js is a runtime environment that allows you to run JavaScript on the server side, built on Chrome's V8 JavaScript engine. It enables developers to build scalable network applications using JavaScript on both frontend and backend.
Building a web server that can handle thousands of concurrent connections efficiently without creating a new thread for each request, making it perfect for real-time applications like chat systems and streaming services.
// Simple Node.js HTTP Server const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World from Node.js!'); }); server.listen(3000, () => { console.log('Server running on port 3000'); });
Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Perfect for handling file uploads while simultaneously serving other requests.
const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); // Register event listener myEmitter.on('event', (data) => { console.log('Event triggered:', data); }); // Emit event myEmitter.emit('event', 'Hello World');
File interaction & manipulation
Essential for reading configuration files, processing uploads, or generating reports. Supports both synchronous and asynchronous operations.
const fs = require('fs'); // Async reading (Non-blocking) fs.readFile('config.json', 'utf8', (err, data) => { if (err) throw err; console.log('Content:', data); }); // Sync reading (Blocking) const data = fs.readFileSync('config.json', 'utf8'); // Writing files fs.writeFile('output.txt', 'Hello', (err) => { if (err) throw err; console.log('Saved!'); });
Server & client functionality
Create HTTP servers and clients, handle requests and responses. Foundation for building REST APIs without external frameworks.
const http = require('http'); const url = require('url'); const server = http.createServer((req, res) => { const parsedUrl = url.parse(req.url, true); if (parsedUrl.pathname === '/api/users') { res.writeHead(200, {'Content-Type': 'application/json'}); res.end(JSON.stringify({users: ['John', 'Jane']})); } else { res.writeHead(404); res.end('Not Found'); } }); server.listen(3000);
const path = require('path');
const os = require('os');
Global process object
The most popular Node.js web framework for building APIs and web applications. Minimalist, flexible, and robust.
const express = require('express'); const app = express(); const port = process.env.PORT || 3000; // Essential Middleware app.use(express.json()); app.use(express.urlencoded({ extended: true })); // Routes app.get('/', (req, res) => { res.json({ message: 'Welcome to our API!' }); }); app.get('/api/users', (req, res) => { res.json([ { id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' } ]); }); app.listen(port, () => { console.log(`Server running on port ${port}`); });
Functions that execute during the request-response cycle. Essential for authentication, logging, error handling, and request validation.
// Custom Logger Middleware const logger = (req, res, next) => { console.log(`${new Date().toISOString()} - ${req.method} ${req.path}`); next(); // Continue to next middleware }; // Authentication Middleware const authenticate = (req, res, next) => { const token = req.header('Authorization'); if (!token) { return res.status(401).json({ error: 'Access denied' }); } next(); }; // Apply middleware app.use(logger); // Global app.use('/api/protected', authenticate); // Route-specific
// Error Handling Middleware app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: 'Something went wrong!', message: err.message }); }); // 404 Handler app.use((req, res) => { res.status(404).json({ error: 'Route not found' }); });
A better way to handle asynchronous operations with cleaner syntax and better error handling compared to callbacks.
const fs = require('fs').promises; // Promise-based file reading fs.readFile('config.json', 'utf8') .then(data => console.log('File:', data)) .catch(err => console.error('Error:', err)); // Promise.all for parallel execution Promise.all([ fs.readFile('file1.txt'), fs.readFile('file2.txt') ]) .then(([data1, data2]) => { console.log('Both files read'); }) .catch(err => console.error(err));
Modern syntax for handling asynchronous operations with synchronous-like code. Easier to read and debug.
const fs = require('fs').promises; async function processFiles() { try { // Sequential execution const data1 = await fs.readFile('file1.txt', 'utf8'); const data2 = await fs.readFile('file2.txt', 'utf8'); const combined = data1 + data2; await fs.writeFile('combined.txt', combined); console.log('Success!'); return combined; } catch (error) { console.error('Error:', error); throw error; } }
| Pattern | Readability | Error Handling | Use Case |
|---|---|---|---|
| Callbacks | Low (Callback Hell) | Manual | Legacy code |
| Promises | Medium | .catch() chain | Parallel operations |
| Async/Await | High | Try/Catch | Modern applications |
Object Data Modeling (ODM) library
Mongoose provides a straightforward, schema-based solution to model your application data. It includes built-in type casting, validation, query building, and business logic hooks.
const mongoose = require('mongoose'); // Connection await mongoose.connect('mongodb://localhost:27017/myapp'); // Define Schema const userSchema = new mongoose.Schema({ name: { type: String, required: true }, email: { type: String, required: true, unique: true }, age: { type: Number, min: 0, max: 120 }, createdAt: { type: Date, default: Date.now } }); const User = mongoose.model('User', userSchema); // CRUD Operations async function userOperations() { // Create const newUser = await User.create({ name: 'John Doe', email: 'john@example.com', age: 30 }); // Read const users = await User.find(); const user = await User.findById(newUser._id); // Update await User.findByIdAndUpdate(user._id, { age: 31 }); // Delete await User.findByIdAndDelete(user._id); }
Model.create()
Insert new documents
Model.find() / findOne()
Query documents
findByIdAndUpdate/Delete
Modify documents
Handle large data efficiently. Perfect for processing large files without loading everything into memory.
const fs = require('fs'); const readline = require('readline'); // Read large files in chunks const stream = fs.createReadStream('large-file.txt', { highWaterMark: 1024 // 1KB chunks }); stream.on('data', (chunk) => { console.log('Received:', chunk.length, 'bytes'); }); // Process line by line const rl = readline.createInterface({ input: fs.createReadStream('data.csv') }); rl.on('line', (line) => { console.log('Line:', line); });
Real-time bidirectional communication. Ideal for chat apps, live notifications, and collaborative tools.
const io = require('socket.io')(server); io.on('connection', (socket) => { console.log('User connected:', socket.id); socket.on('joinRoom', (roomId) => { socket.join(roomId); socket.to(roomId).emit('userJoined'); }); socket.on('sendMessage', (data) => { io.to(data.roomId).emit('newMessage', { userId: socket.id, message: data.message, timestamp: new Date() }); }); });
Input validation, sanitization, and protection against common attacks using Joi and validator.
const Joi = require('joi'); const userSchema = Joi.object({ name: Joi.string().min(2).required(), email: Joi.string().email().required(), password: Joi.string().min(8).pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])/) }); const validate = (schema) => { return (req, res, next) => { const { error } = schema.validate(req.body); if (error) { return res.status(400).json({ error: error.details[0].message }); } next(); }; }; app.post('/api/users', validate(userSchema), handler);
Containerize your Node.js application for consistent deployment across environments.
FROM node:18-alpine WORKDIR /usr/src/app # Copy dependencies COPY package*.json ./ RUN npm ci --only=production # Copy code COPY . . # Security: Run as non-root RUN addgroup -g 1001 -S nodejs RUN adduser -S nodejs -u 1001 USER nodejs EXPOSE 3000 CMD ["node", "server.js"]
const request = require('supertest'); const app = require('./app'); describe('User API', () => { test('GET /api/users - should return all users', async () => { const response = await request(app) .get('/api/users') .expect(200); expect(response.body).toHaveLength(2); expect(response.body[0]).toHaveProperty('name'); }); test('POST /api/users - should create user', async () => { const userData = { name: 'New User', email: 'new@test.com' }; const response = await request(app) .post(span class="syntax-string">'/api/users') .send(userData) .expect(201); expect(response.body.name).toBe(userData.name); }); });