Beginner Node.js Interview Questions and Answers

๐Ÿ“‹ Table of Contents โ–พ
  1. Questions & Answers
  2. 📝 Knowledge Check

🟢 Beginner Node.js Interview Questions

This lesson covers the fundamental Node.js concepts every backend developer must know. Master the event loop, modules, npm, the core built-in modules, callbacks, Promises, async/await, and the file system. These questions mirror what interviewers ask at junior and entry-level Node.js roles.

Questions & Answers

01 What is Node.js and what makes it different from browser JavaScript?

Core Node.js is an open-source, cross-platform JavaScript runtime built on Chrome’s V8 JavaScript engine. It allows JavaScript to run outside the browser โ€” on servers, desktops, IoT devices, and command-line tools.

Key differences from browser JavaScript:

  • No DOM or Browser APIs โ€” no window, document, localStorage, or navigator. Node provides different globals: process, Buffer, __dirname, __filename.
  • File system access โ€” Node can read and write files (fs module). Browsers cannot for security reasons.
  • Module system โ€” Node uses CommonJS (require()) or ES Modules (import). Browsers use ES Modules only.
  • Built-in modules โ€” http, fs, path, os, crypto, net, child_process โ€” none of which exist in browsers.
  • Single version โ€” you control the exact Node.js version; browsers vary and need polyfills.
// Node.js only โ€” impossible in a browser
const fs = require('fs');
fs.readFileSync('config.json'); // read a file from disk

// Available in Node only
console.log(process.env.NODE_ENV);  // environment variables
console.log(__dirname);             // current directory path

02 What is the Node.js Event Loop? Give a simple explanation.

Core The event loop is the mechanism that allows Node.js to perform non-blocking I/O operations despite JavaScript being single-threaded. It continuously checks for work to do and delegates I/O tasks (file reads, network calls) to the operating system or thread pool, then picks up the results when they are ready.

Simplified lifecycle:

// 1. Synchronous code runs first (call stack)
console.log('A'); // prints A

// 2. Async tasks are offloaded and their callbacks are queued
setTimeout(() => console.log('B'), 0);   // queued โ€” runs after current stack
Promise.resolve().then(() => console.log('C')); // microtask โ€” runs before timers

// 3. Remaining synchronous code runs
console.log('D'); // prints D

// Output order: A โ†’ D โ†’ C โ†’ B
// Microtasks (Promises) drain BEFORE timer callbacks

Event loop phases (in order): Timers (setTimeout, setInterval) โ†’ Pending I/O callbacks โ†’ Idle/Prepare โ†’ Poll (wait for I/O) โ†’ Check (setImmediate) โ†’ Close callbacks. Between each phase, the microtask queue (Promises, queueMicrotask) drains completely.

03 What is npm? What is the difference between dependencies and devDependencies?

npm npm (Node Package Manager) is the default package manager for Node.js. It manages project dependencies, scripts, and publishing packages to the npm registry.

# Initialise a project
npm init -y

# Install a runtime dependency (added to "dependencies")
npm install express mongoose

# Install a development-only dependency (added to "devDependencies")
npm install --save-dev jest eslint nodemon typescript

# Install globally (CLI tools, not project-specific)
npm install -g nodemon

# Install exact versions from package-lock.json (CI/CD)
npm ci

dependencies vs devDependencies:

  • dependencies โ€” packages required at runtime in production: express, mongoose, bcryptjs, jsonwebtoken. Installed when running npm install in production.
  • devDependencies โ€” packages only needed during development and testing: jest, eslint, nodemon, typescript. Excluded from production installs (npm install --omit=dev).

Keeping devDependencies separate reduces production deployment size and attack surface.

04 What is the CommonJS module system? How does require() work?

Modules CommonJS (CJS) is Node.js’s original module system. Each file is its own module with its own scope. You export values with module.exports and import them with require().

// math.js โ€” exporting
function add(a, b) { return a + b; }
function subtract(a, b) { return a - b; }

module.exports = { add, subtract };     // export an object
// OR: module.exports = add;            // export a single value
// OR: exports.add = add;               // shorthand (same as module.exports.add)

// app.js โ€” importing
const math = require('./math');          // relative path โ€” .js extension optional
console.log(math.add(2, 3));            // 5

const { add, subtract } = require('./math'); // destructuring

// Built-in modules (no path prefix)
const fs   = require('fs');
const path = require('path');
const http = require('http');

// npm packages (no path prefix โ€” resolved from node_modules)
const express = require('express');

require() caching: The first call to require('./module') executes the module and caches the result. All subsequent calls return the same cached exports โ€” modules are singletons. Use delete require.cache[require.resolve('./module')] to bust the cache (rarely needed).

05 What are ES Modules (ESM) in Node.js? How do they differ from CommonJS?

Modules ES Modules (ESM) is the official JavaScript module standard, available in Node.js since v12 (stable in v14+). Unlike CommonJS, ESM uses import/export syntax and is statically analysable (enabling tree-shaking).

// Enable ESM: use .mjs extension OR set "type": "module" in package.json

// math.mjs โ€” exporting
export function add(a, b)      { return a + b; }
export function subtract(a, b) { return a - b; }
export default { add, subtract }; // default export

// app.mjs โ€” importing
import { add, subtract } from './math.mjs'; // must include extension in ESM
import math from './math.mjs';              // default import
import * as allMath from './math.mjs';      // namespace import

// Dynamic import (works in both CJS and ESM)
const module = await import('./feature.mjs');

Key differences from CommonJS:

  • Static vs dynamic โ€” ESM imports are resolved at parse time; require() runs at execution time
  • Top-level await โ€” ESM supports await at the top level; CJS does not
  • No __dirname/__filename in ESM โ€” use import.meta.url and fileURLToPath instead
  • File extensions required โ€” ESM import must include the full extension (.js, .mjs)
  • One-way compatibility โ€” ESM can import CJS; CJS cannot require() an ESM module
06 What is a callback function in Node.js? What is callback hell?

Async A callback is a function passed as an argument to another function, to be called when an asynchronous operation completes. Node.js uses the error-first callback convention: the first parameter is always an error (or null), the second is the result.

// Error-first callback convention
const fs = require('fs');
fs.readFile('./data.json', 'utf8', (err, data) => {
  if (err) return console.error('Error:', err.message);
  console.log('Data:', data);
});

// Callback hell โ€” deeply nested async operations
getUserById(userId, (err, user) => {
  if (err) return handleError(err);
  getOrdersByUser(user.id, (err, orders) => {
    if (err) return handleError(err);
    getProductDetails(orders[0].productId, (err, product) => {
      if (err) return handleError(err);
      sendConfirmationEmail(user.email, product, (err) => {
        if (err) return handleError(err);
        console.log('Done!'); // deeply nested, hard to read and maintain
      });
    });
  });
});

Solutions to callback hell:

  • Named functions โ€” extract callbacks into named functions
  • Promises โ€” chain .then() calls in a flat structure
  • async/await โ€” write async code that looks synchronous (best approach)
07 What are Promises in Node.js? How do you use them?

Async A Promise represents the eventual result of an asynchronous operation. It can be in one of three states: pending, fulfilled (resolved with a value), or rejected (failed with a reason).

// Creating a Promise
const fetchUser = (id) => new Promise((resolve, reject) => {
  db.query('SELECT * FROM users WHERE id = ?', [id], (err, rows) => {
    if (err) reject(err);
    else resolve(rows[0]);
  });
});

// Consuming with .then()/.catch()/.finally()
fetchUser(1)
  .then(user  => console.log('User:', user))
  .catch(err  => console.error('Error:', err.message))
  .finally(() => console.log('Done'));

// Promise combinators
Promise.all([fetchUser(1), fetchUser(2)])          // both must resolve
  .then(([u1, u2]) => console.log(u1, u2));

Promise.allSettled([fetchUser(1), fetchUser(99)])   // all complete (even if rejected)
  .then(results => results.forEach(r => console.log(r.status, r.value || r.reason)));

Promise.race([slowOp(), fastOp()])                  // first to settle wins
  .then(result => console.log('Winner:', result));

Promise.any([failOp(), successOp()])                // first to RESOLVE wins
  .then(result => console.log('First success:', result));

08 What is async/await? How does it relate to Promises?

Async async/await is syntactic sugar over Promises that makes asynchronous code look and behave like synchronous code. An async function always returns a Promise. await pauses execution inside the function until the Promise settles.

// Promise chain โ€” working but verbose
function getOrderTotal(userId) {
  return getUser(userId)
    .then(user => getOrders(user.id))
    .then(orders => orders.reduce((sum, o) => sum + o.total, 0))
    .catch(err => { throw new Error('Failed: ' + err.message); });
}

// async/await โ€” same logic, much cleaner
async function getOrderTotal(userId) {
  try {
    const user   = await getUser(userId);       // pauses here
    const orders = await getOrders(user.id);    // pauses here
    return orders.reduce((sum, o) => sum + o.total, 0);
  } catch (err) {
    throw new Error('Failed: ' + err.message);
  }
}

// Parallel execution โ€” don't await sequentially if operations are independent
async function loadDashboard(userId) {
  // โŒ Sequential โ€” total time = user time + orders time + recs time
  // const user   = await getUser(userId);
  // const orders = await getOrders(userId);

  // โœ… Parallel โ€” total time = max(user, orders, recs)
  const [user, orders, recommendations] = await Promise.all([
    getUser(userId),
    getOrders(userId),
    getRecommendations(userId)
  ]);
  return { user, orders, recommendations };
}

09 What is the fs module? How do you read and write files?

Core Modules The fs (file system) module provides APIs for interacting with the file system. It has synchronous, callback-based, and Promise-based versions.

const fs   = require('fs');
const fsP  = require('fs/promises'); // Promise-based (Node 14+)
const path = require('path');

// โ”€โ”€ Synchronous (blocks event loop โ€” avoid in servers) โ”€โ”€
const data = fs.readFileSync('./config.json', 'utf8');
fs.writeFileSync('./output.txt', 'Hello World', 'utf8');

// โ”€โ”€ Promise-based (recommended in async code) โ”€โ”€
async function processFile() {
  // Read
  const content = await fsP.readFile('./data.json', 'utf8');
  const parsed  = JSON.parse(content);

  // Write
  await fsP.writeFile('./result.json', JSON.stringify(parsed, null, 2));

  // Append
  await fsP.appendFile('./log.txt', `${new Date().toISOString()} โ€” processed\n`);

  // Check if file/dir exists
  try { await fsP.access('./config.json'); }
  catch { console.log('File not found'); }

  // Read directory contents
  const files = await fsP.readdir('./src');

  // Create directory (recursive = create parent dirs too)
  await fsP.mkdir('./output/reports', { recursive: true });

  // Delete a file
  await fsP.unlink('./temp.txt');

  // File stats
  const stats = await fsP.stat('./data.json');
  console.log(stats.size, stats.mtime);
}

10 What is the path module and why is it important?

Core Modules The path module provides utilities for working with file and directory paths. It is essential because path separators differ between operating systems (Windows uses \, POSIX uses /). Using path makes code cross-platform.

const path = require('path');

// Join path segments safely (handles OS differences)
const filePath = path.join(__dirname, 'public', 'images', 'logo.png');
// Linux/Mac: /home/user/app/public/images/logo.png
// Windows:   C:\Users\user\app\public\images\logo.png

// Resolve to absolute path
const abs = path.resolve('config', 'settings.json');
// Returns absolute path from current working directory

// Get directory name
path.dirname('/home/user/app/server.js'); // /home/user/app

// Get file name
path.basename('/home/user/app/server.js');      // server.js
path.basename('/home/user/app/server.js', '.js'); // server (without extension)

// Get extension
path.extname('report.2026.pdf'); // .pdf

// Parse path into components
path.parse('/home/user/app/server.js');
// { root: '/', dir: '/home/user/app', base: 'server.js',
//   ext: '.js', name: 'server' }

// Normalise (resolve . and .. segments)
path.normalize('/home/user/../user/app/./server.js');
// /home/user/app/server.js

Always use path.join(__dirname, ...) to construct absolute paths to files relative to the current module. Never concatenate paths with string operators.

11 What is the http module? How do you create a basic HTTP server?

Core Modules The http module is Node’s built-in HTTP server and client. While Express is used in practice, understanding the raw http module shows what Express builds on top of.

const http = require('http');

const server = http.createServer((req, res) => {
  // req โ€” http.IncomingMessage (readable stream)
  console.log(req.method, req.url, req.headers);

  // Parse URL and query string
  const url = new URL(req.url, `http://${req.headers.host}`);
  const id  = url.searchParams.get('id');

  // Route based on method and path
  if (req.method === 'GET' && url.pathname === '/users') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify([{ id: 1, name: 'Alice' }]));
    return;
  }

  if (req.method === 'POST' && url.pathname === '/users') {
    let body = '';
    req.on('data', chunk => body += chunk);
    req.on('end', () => {
      const data = JSON.parse(body);
      res.writeHead(201, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ id: 2, ...data }));
    });
    return;
  }

  // 404 fallback
  res.writeHead(404, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ error: 'Not found' }));
});

server.listen(3000, () => console.log('Server on http://localhost:3000'));

12 What is the process object in Node.js?

Core The process object is a global object providing information and control over the current Node.js process. It is available everywhere without require().

// Environment
console.log(process.env.NODE_ENV);         // "development" / "production"
console.log(process.env.PORT);             // custom env variable

// Process info
console.log(process.pid);                  // process ID
console.log(process.version);             // Node.js version e.g. "v20.11.0"
console.log(process.platform);            // "linux", "darwin", "win32"
console.log(process.arch);               // "x64", "arm64"

// Working directory
console.log(process.cwd());               // current working directory
process.chdir('/tmp');                     // change working directory

// Memory usage
const mem = process.memoryUsage();
console.log(Math.round(mem.rss / 1024 / 1024) + ' MB RSS');

// Exit
process.exit(0);    // success exit
process.exit(1);    // error exit

// Command-line arguments
// node app.js --port 3000 --env prod
console.log(process.argv); // ['node', 'app.js', '--port', '3000', '--env', 'prod']

// Standard I/O
process.stdout.write('Hello');
process.stderr.write('Error message');
process.stdin.on('data', d => console.log('Input:', d.toString()));

// Signal handlers
process.on('SIGTERM', () => { console.log('Shutting down...'); process.exit(0); });
process.on('uncaughtException', (err) => { console.error(err); process.exit(1); });
process.on('unhandledRejection', (reason) => { console.error(reason); });

13 What is the os module? What information does it provide?

Core Modules The os module provides operating system-related utility methods and properties โ€” useful for system monitoring, scaling decisions, and cross-platform compatibility.

const os = require('os');

// CPU information
console.log(os.cpus());          // array of CPU cores with model, speed, times
console.log(os.cpus().length);   // number of CPU cores โ€” use for clustering

// Memory
console.log(os.totalmem());      // total memory in bytes
console.log(os.freemem());       // available free memory in bytes
const freeGB = (os.freemem() / 1024 ** 3).toFixed(2);

// Network interfaces
console.log(os.networkInterfaces()); // all NICs with IP addresses

// System info
console.log(os.hostname());      // machine hostname
console.log(os.platform());      // 'linux', 'darwin', 'win32'
console.log(os.arch());          // 'x64', 'arm64'
console.log(os.release());       // OS version string
console.log(os.uptime());        // system uptime in seconds

// User info
console.log(os.userInfo());      // { username, homedir, shell }
console.log(os.homedir());       // /home/username

// Path separator constants
console.log(os.EOL);             // line ending: '\n' (POSIX) or '\r\n' (Windows)
console.log(os.tmpdir());        // temporary files directory

14 What is the EventEmitter in Node.js?

Core EventEmitter is the foundation of Node.js’s event-driven architecture. Most Node.js core objects (streams, HTTP server, child processes) extend EventEmitter. You can create your own emitters to build observable objects.

const EventEmitter = require('events');

// Custom event emitter
class OrderService extends EventEmitter {
  async placeOrder(orderData) {
    const order = await createOrder(orderData);
    this.emit('orderPlaced', order);           // emit an event with data
    this.emit('notification', { type: 'email', to: orderData.email });
    return order;
  }
}

const orders = new OrderService();

// Register listeners
orders.on('orderPlaced', (order) => {
  console.log('New order:', order.id);
  updateInventory(order.items);
});

orders.on('notification', async (note) => {
  await sendEmail(note.to, 'Your order is confirmed!');
});

// One-time listener
orders.once('firstOrder', (order) => console.log('First order ever!'));

// Remove a listener
const handler = (order) => console.log(order);
orders.on('orderPlaced', handler);
orders.off('orderPlaced', handler);           // or: orders.removeListener(...)

// Error event โ€” always handle, otherwise Node throws
orders.on('error', (err) => console.error('Order error:', err));
orders.emit('error', new Error('Payment failed'));

15 What is the Buffer class in Node.js?

Core Buffer is a global class for working with binary data โ€” raw bytes โ€” outside the V8 heap. It is used extensively for streams, file I/O, network data, cryptography, and binary protocols.

// Creating Buffers
const buf1 = Buffer.alloc(10);                 // 10 zero-filled bytes
const buf2 = Buffer.alloc(10, 0xff);           // 10 bytes filled with 0xff
const buf3 = Buffer.from('Hello');             // from string (default: UTF-8)
const buf4 = Buffer.from('48656c6c6f', 'hex'); // from hex string
const buf5 = Buffer.from([72, 101, 108, 108, 111]); // from byte array

// Convert to string
console.log(buf3.toString('utf8'));   // "Hello"
console.log(buf3.toString('base64')); // "SGVsbG8="
console.log(buf3.toString('hex'));    // "48656c6c6f"

// Manipulate
buf1.write('Node');       // write string into buffer
console.log(buf1[0]);     // read individual byte

// Copy and slice
const copy = buf3.slice(0, 3);  // Buffer view: "Hel" (shares memory)
const copy2 = buf3.subarray(0, 3); // same as slice (preferred)

// Compare and concatenate
Buffer.compare(buf3, buf4);      // 0 = equal, -1 = before, 1 = after
const merged = Buffer.concat([buf3, Buffer.from(' World')]); // "Hello World"

// Check encoding
Buffer.isEncoding('base64'); // true

16 What are timers in Node.js? What is the difference between setTimeout and setImmediate?

Async

// setTimeout โ€” execute after at least N milliseconds
const timer = setTimeout(() => console.log('timeout'), 1000);
clearTimeout(timer); // cancel before firing

// setInterval โ€” execute repeatedly every N milliseconds
const interval = setInterval(() => console.log('tick'), 500);
clearInterval(interval); // stop repeating

// setImmediate โ€” execute in the Check phase, AFTER I/O callbacks, BEFORE timers
setImmediate(() => console.log('immediate'));

// queueMicrotask โ€” highest priority, runs before any macrotask
queueMicrotask(() => console.log('microtask'));

// process.nextTick โ€” runs before ANY other async callback (before microtasks in older docs)
// Technically runs between current operation and next event loop iteration
process.nextTick(() => console.log('nextTick'));

// Execution order within one event loop turn:
// 1. Synchronous code
// 2. process.nextTick callbacks
// 3. Promise microtasks (queueMicrotask)
// 4. setImmediate callbacks (Check phase)
// 5. setTimeout (Timers phase โ€” if delay elapsed)

// setTimeout vs setImmediate order depends on context:
// Outside I/O callback: unpredictable (OS-dependent)
// Inside I/O callback: setImmediate ALWAYS runs before setTimeout(fn, 0)

17 What is the url module? How do you parse URLs in Node.js?

Core Modules Modern Node.js uses the WHATWG URL API (globally available as URL and URLSearchParams) โ€” the same API as browsers.

// WHATWG URL API โ€” global in Node.js 10+
const url = new URL('https://example.com:8080/products?category=books&sort=price#top');

console.log(url.href);         // full URL string
console.log(url.protocol);     // "https:"
console.log(url.host);         // "example.com:8080"
console.log(url.hostname);     // "example.com"
console.log(url.port);         // "8080"
console.log(url.pathname);     // "/products"
console.log(url.search);       // "?category=books&sort=price"
console.log(url.hash);         // "#top"
console.log(url.origin);       // "https://example.com:8080"

// URLSearchParams โ€” manipulate query strings
const params = url.searchParams;
console.log(params.get('category'));     // "books"
console.log(params.has('sort'));         // true
params.set('page', '2');
params.append('tag', 'fiction');
params.delete('sort');
console.log(params.toString());         // "category=books&page=2&tag=fiction"

// Relative URL resolution
const base = new URL('https://example.com/products/');
const rel  = new URL('../about', base);
console.log(rel.href); // "https://example.com/about"

18 What is the crypto module? How do you hash passwords?

Core Modules The crypto module provides cryptographic functionality: hashing, HMAC, encryption, random bytes, and key derivation. For password hashing, use bcrypt (or Node’s built-in crypto.scrypt / crypto.pbkdf2).

const crypto = require('crypto');

// Hashing (one-way, for integrity โ€” NOT for passwords)
const hash = crypto.createHash('sha256').update('hello').digest('hex');
// 2cf24dba... (deterministic โ€” same input always gives same output)

// HMAC (hash + secret key โ€” for message authentication)
const hmac = crypto.createHmac('sha256', 'secret-key').update('message').digest('hex');

// Secure random bytes (for tokens, salts)
const token = crypto.randomBytes(32).toString('hex'); // 64-char hex string
const uuid  = crypto.randomUUID(); // "550e8400-e29b-41d4-a716-446655440000"

// Password hashing with scrypt (built-in, strong)
async function hashPassword(password) {
  const salt   = crypto.randomBytes(16).toString('hex');
  const hash   = await new Promise((resolve, reject) =>
    crypto.scrypt(password, salt, 64, (err, key) =>
      err ? reject(err) : resolve(key.toString('hex'))
    )
  );
  return `${salt}:${hash}`;
}

async function verifyPassword(password, stored) {
  const [salt, hash] = stored.split(':');
  const keyBuffer = Buffer.from(hash, 'hex');
  const derived = await new Promise((res, rej) =>
    crypto.scrypt(password, salt, 64, (err, k) => err ? rej(err) : res(k))
  );
  return crypto.timingSafeEqual(derived, keyBuffer); // constant-time comparison
}

19 What is the util module? What are its most useful methods?

Core Modules The util module provides utility functions useful for debugging, type checking, and working with callbacks.

const util = require('util');

// util.promisify โ€” convert callback-based functions to Promises
const fs        = require('fs');
const readFile  = util.promisify(fs.readFile);
const writeFile = util.promisify(fs.writeFile);
const data = await readFile('./config.json', 'utf8'); // now returns a Promise

// util.callbackify โ€” convert async/Promise functions to callback style
const asyncFn      = async (x) => x * 2;
const callbackFn   = util.callbackify(asyncFn);
callbackFn(5, (err, result) => console.log(result)); // 10

// util.inspect โ€” deep string representation of objects (better than JSON.stringify)
console.log(util.inspect({ a: [1,2,3], b: { c: 'deep' } }, { depth: null, colors: true }));

// util.format โ€” printf-style string formatting
util.format('Hello %s, you are %d years old', 'Alice', 29); // "Hello Alice, you are 29 years old"

// util.isDeepStrictEqual โ€” deep equality check
util.isDeepStrictEqual({ a: 1 }, { a: 1 }); // true
util.isDeepStrictEqual({ a: 1 }, { a: '1' }); // false (strict)

// util.types โ€” type checking
util.types.isAsyncFunction(async () => {});  // true
util.types.isPromise(Promise.resolve());       // true
util.types.isMap(new Map());                   // true

20 How do you handle errors in Node.js? What is the difference between operational and programmer errors?

Error Handling

  • Operational errors โ€” expected, recoverable failures that are part of normal operation: file not found, network timeout, invalid user input, database connection failure. Handle gracefully with error messages to the user.
  • Programmer errors โ€” bugs: TypeError: cannot read property of undefined, wrong function arguments, logic errors. These indicate a bug in the code. The process should restart.
// Synchronous error โ€” use try/catch
try {
  const data = JSON.parse(invalidJson); // throws SyntaxError (programmer or operational)
} catch (err) {
  console.error('Parse error:', err.message);
}

// Async error โ€” use try/catch with async/await
async function fetchData(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) throw new Error(`HTTP ${response.status}`); // operational
    return response.json();
  } catch (err) {
    throw err; // re-throw for caller to handle
  }
}

// Custom error classes โ€” distinguish error types
class AppError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.name = 'AppError';
    this.statusCode = statusCode;
    this.isOperational = true;
  }
}
throw new AppError('User not found', 404);

// Global safety nets (last resort โ€” not a substitute for proper handling)
process.on('uncaughtException',  err => { logger.error(err); process.exit(1); });
process.on('unhandledRejection', reason => { logger.error(reason); });

21 What is the package.json scripts field? Give useful examples.

npm The scripts field in package.json defines shorthand commands runnable via npm run <script>. Scripts have access to locally installed node_modules/.bin executables โ€” no global install needed.

{
  "scripts": {
    "start":        "node dist/server.js",
    "dev":          "nodemon src/server.js",
    "build":        "tsc",
    "test":         "jest",
    "test:watch":   "jest --watch",
    "test:coverage":"jest --coverage",
    "lint":         "eslint src/**/*.ts",
    "lint:fix":     "eslint src/**/*.ts --fix",
    "format":       "prettier --write src/**/*.ts",
    "db:migrate":   "knex migrate:latest",
    "db:seed":      "knex seed:run",
    "docker:up":    "docker-compose up -d",

    "prestart":     "npm run build",    // runs automatically BEFORE "start"
    "posttest":     "npm run lint"      // runs automatically AFTER "test"
  }
}

// Run scripts:
// npm start            โ†’ "node dist/server.js"
// npm test             โ†’ "jest"
// npm run dev          โ†’ "nodemon src/server.js"
// npm run build        โ†’ "tsc"

// Pass extra arguments:
// npm test -- --testNamePattern="auth"   (the -- separates npm args from script args)

// Run multiple scripts in sequence:
// "build": "tsc && cp -r public dist/"   (runs tsc, then copy if tsc succeeds)
// "build": "tsc; cp -r public dist/"     (runs both regardless)

22 What is the difference between package.json and package-lock.json?

npm

  • package.json โ€” human-authored manifest declaring the project’s name, version, scripts, and dependency ranges (e.g., "express": "^4.18.0" โ€” any version โ‰ฅ4.18.0 and <5.0.0). Committed to source control. Shared across the team.
  • package-lock.json โ€” auto-generated by npm. Records the exact resolved version of every package and sub-dependency (e.g., "express": "4.18.3"). Ensures every developer and CI system installs the exact same versions. Must be committed to source control.
# Installs based on package.json ranges (may update patch/minor versions)
npm install

# Installs EXACT versions from package-lock.json (recommended for CI)
npm ci

# Why npm ci for CI/CD:
# - Faster (skips resolution step)
# - Fails if package-lock.json is out of sync with package.json
# - Deletes node_modules first (clean install)
# - Never modifies package-lock.json

The ^ prefix means “compatible with” (allows minor and patch updates). ~ allows only patch updates. No prefix means exact version. In production, consider pinning exact versions or using npm ci to ensure reproducibility.

📝 Knowledge Check

Test your understanding of Node.js fundamentals with these five questions.

🧠 Quiz Question 1 of 5

What is the correct order of execution for the following Node.js code?
console.log('A'); setTimeout(() => console.log('B'), 0); Promise.resolve().then(() => console.log('C')); console.log('D');





🧠 Quiz Question 2 of 5

What is the Node.js error-first callback convention?





🧠 Quiz Question 3 of 5

What does require() caching mean in Node.js CommonJS modules?





🧠 Quiz Question 4 of 5

Which npm command installs the exact dependency versions from package-lock.json and is recommended for CI/CD pipelines?





🧠 Quiz Question 5 of 5

What is the primary advantage of using async/await over raw Promise .then() chains?