Node.js Runtime Architecture and Core Modules
Runtime Environment Overview
Node.js operates as a JavaScript runtime built on Google's V8 engine. Unlike browsers which embed V8 alongside rendering engines and DOM APIs, Node.js extends V8 with system-level capabilities including file operations, network I/O, cryptography, and compression utilities.
The architecture flows through V8 → Node.js bindings → libuv event loop. Libuv, written in C, handles the event loop, file system operations, networikng, and thread pooling.
File System Operations
The fs module provides cross-platform file manipulation capabilities:
const fs = require('fs');
// Synchronous reading
const syncData = fs.readFileSync('document.txt', 'utf-8');
console.log(syncData);
// Asynchronous callback
fs.readFile('document.txt', 'utf-8', (err, data) => {
if (err) throw err;
console.log(data);
});
// Promise-based approach
fs.promises.readFile('document.txt', 'utf-8')
.then(data => console.log(data))
.catch(err => console.error(err));
File operations support various flags: 'w' (write), 'r' (read), 'a' (append), with modifiers like '+' for read/write combinations.
Event-Driven Programming
Node.js core APIs rely on event-driven patterns using the EventEmitter class:
const EventEmitter = require('events');
const emitter = new EventEmitter();
emitter.on('dataReceived', (payload) => {
console.log('Processing:', payload);
});
emitter.once('startup', () => {
console.log('Initialization complete');
});
emitter.emit('dataReceived', { id: 1, content: 'sample' });
Binary Data Handling
Buffer objects store raw binary data, essential for file processing and network communications:
// Creating buffers
const buffer1 = Buffer.alloc(10); // 10-byte zero-filled buffer
const buffer2 = Buffer.from('Hello World', 'utf-8');
const buffer3 = Buffer.from([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
console.log(buffer2.toString()); // "Hello World"
console.log(buffer2.length); // 11 bytes
Streaming Data
Streams process data incrementally rather than loading everything into memory:
const fs = require('fs');
// Readable stream
const readStream = fs.createReadStream('large-file.mp4', {
start: 0,
end: 1000,
highWaterMark: 64 * 1024
});
readStream.on('data', (chunk) => {
console.log(`Received ${chunk.length} bytes`);
});
// Writable stream
const writeStream = fs.createWriteStream('output.txt');
writeStream.write('First chunk\n');
writeStream.write('Second chunk\n');
writeStream.end();
// Piping streams
fs.createReadStream('source.txt').pipe(fs.createWriteStream('destination.txt'));
Web Server Development
HTTP Module Fundamentals
Creating basic HTTP servers:
const http = require('http');
const server = http.createServer((req, res) => {
const { method, url, headers } = req;
if (url === '/api/users' && method === 'GET') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify([{ id: 1, name: 'John' }]));
} else {
res.writeHead(404);
res.end('Not Found');
}
});
server.listen(3000, '0.0.0.0', () => {
console.log('Server running on port 3000');
});
Express Framework
Express simplifies web server development through middleware patterns:
const express = require('express');
const app = express();
// Middleware for parsing JSON
app.use(express.json());
// Route handlers
app.get('/users/:id', (req, res) => {
res.json({ userId: req.params.id, name: 'Sample User' });
});
app.post('/users', (req, res) => {
const userData = req.body;
res.status(201).json({ id: 123, ...userData });
});
// Error handling middleware
app.use((err, req, res, next) => {
res.status(500).json({ error: err.message });
});
app.listen(3000);
Koa Framework
Koa uses async/await for cleaner middleware flow:
const Koa = require('koa');
const Router = require('@koa/router');
const app = new Koa();
const router = new Router();
router.get('/users/:id', async (ctx) => {
ctx.body = { userId: ctx.params.id, name: 'Koa User' };
});
router.post('/users', async (ctx) => {
const userData = ctx.request.body;
ctx.status = 201;
ctx.body = { id: 456, ...userData };
});
app.use(require('koa-bodyparser')());
app.use(router.routes());
app.listen(3000);
File Upload Handling
Processing multipart form data:
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
app.post('/upload', upload.single('avatar'), (req, res) => {
console.log(req.file);
res.json({ message: 'Upload successful' });
});
// Multiple files
app.post('/gallery', upload.array('photos', 5), (req, res) => {
res.json({ count: req.files.length });
});
Database Integration
MySQL Operations
Connecting to relational databases:
const mysql = require('mysql2');
const connection = mysql.createConnection({
host: 'localhost',
user: 'developer',
password: 'secret',
database: 'app_data'
});
// Query execution
connection.execute(
'SELECT * FROM users WHERE age > ?',
[18],
(err, results) => {
if (err) throw err;
console.log(results);
}
);
// Prepared statements prevent SQL injection
connection.execute(
'INSERT INTO products (name, price) VALUES (?, ?)',
['Laptop', 999.99]
);
Authentication Mechanisms
JSON Web Tokens for stateless authentication:
const jwt = require('jsonwebtoken');
const SECRET_KEY = 'your-secret-key';
// Token generation
app.post('/login', (req, res) => {
const { username, password } = req.body;
// Validate credentials
if (validateUser(username, password)) {
const token = jwt.sign(
{ userId: 123, username },
SECRET_KEY,
{ expiresIn: '1h' }
);
res.json({ token });
} else {
res.status(401).json({ error: 'Invalid credentials' });
}
});
// Token verification middleware
const authenticateToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, SECRET_KEY, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
};
app.get('/protected', authenticateToken, (req, res) => {
res.json({ message: 'Access granted', user: req.user });
});