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.