🟢 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, ornavigator. Node provides different globals:process,Buffer,__dirname,__filename. - File system access โ Node can read and write files (
fsmodule). 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 runningnpm installin 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
awaitat the top level; CJS does not - No
__dirname/__filenamein ESM โ useimport.meta.urlandfileURLToPathinstead - File extensions required โ ESM
importmust 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.