Node.js Basics
Running Node
Execute scripts and REPL
node script.js # run a script
node -e 'console.log(42)' # evaluate expression
node --watch script.js # auto-restart on changes (Node 18+)
node # REPL
File System
Read and write files with fs/promises
import { readFile, writeFile, readdir, stat } from "fs/promises";
import { existsSync } from "fs";
// Read file
const content = await readFile("/etc/hostname", "utf-8");
console.log(content.trim());
// Write file
await writeFile("/tmp/output.txt", "hello\n");
// Read JSON config
const config = JSON.parse(await readFile("config.json", "utf-8"));
// List directory
const files = await readdir(".", { withFileTypes: true });
const dirs = files.filter(f => f.isDirectory()).map(f => f.name);
// Check existence
if (existsSync("config.json")) { ... }
// File stats
const info = await stat("data.txt");
console.log(`Size: ${info.size}, Modified: ${info.mtime}`);
Always use fs/promises (async) over fs (sync) in production code. Sync I/O blocks the event loop.
Path Handling
Cross-platform path operations
import path from "path";
path.join("src", "utils", "index.js"); // "src/utils/index.js"
path.resolve(".", "config.json"); // "/home/user/project/config.json"
path.basename("/etc/hosts"); // "hosts"
path.dirname("/etc/hosts"); // "/etc"
path.extname("data.json"); // ".json"
path.parse("/etc/hosts");
// { root: '/', dir: '/etc', base: 'hosts', ext: '', name: 'hosts' }
Process & Environment
Access environment and process info
// Environment variables
const port = process.env.PORT ?? "8080";
const mode = process.env.NODE_ENV ?? "development";
// Command-line arguments
const args = process.argv.slice(2); // skip node and script path
console.log("Args:", args);
// Exit
process.exit(0); // success
process.exit(1); // failure
// Current directory
process.cwd();
// stdin
import { createInterface } from "readline";
const rl = createInterface({ input: process.stdin });
for await (const line of rl) {
console.log("Got:", line);
}
Child Processes
Execute shell commands from Node
import { exec, execSync, spawn } from "child_process";
// Sync — blocks, returns stdout
const hostname = execSync("hostname").toString().trim();
// Async with promise wrapper
import { promisify } from "util";
const execAsync = promisify(exec);
const { stdout, stderr } = await execAsync("ls -la");
// spawn — streaming I/O for long-running commands
const child = spawn("ping", ["-c", "4", "10.50.1.1"]);
child.stdout.on("data", (data) => process.stdout.write(data));
child.on("close", (code) => console.log(`exit: ${code}`));
exec buffers the entire output. spawn streams it — use spawn for commands that produce large output.
HTTP Server
Minimal HTTP server without frameworks
import { createServer } from "http";
const server = createServer((req, res) => {
if (req.url === "/health" && req.method === "GET") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ status: "ok" }));
} else {
res.writeHead(404);
res.end("not found");
}
});
server.listen(8080, () => {
console.log("Listening on http://localhost:8080");
});
The built-in http module is low-level. For real applications, use Express, Fastify, or Hono.