Phase 5 · Node.js & Full StackModule 31~44 min read

Node.js Fundamentals

Run JavaScript on the server and understand Node's processes, modules, environment, and event-driven model.

What you'll learn

Node.js combines a JavaScript engine with server-oriented host APIs. Production programs treat the process, environment, modules, events, and shutdown lifecycle as explicit boundaries.

By the end of this lesson, you'll be able to:

  • Use Node ESM and process APIs
  • Build a small command-line program
  • Handle signals and graceful shutdown

Core mental model

Use this decision table as a compact reference. Focus on what each tool means and when it earns its place in production code.

ConceptWhat it meansDecision rule
ProcessRunning program with arguments, environment, streams, and exit statusTreat environment and arguments as untrusted configuration
EventEmitterSynchronous in-process event dispatchUse for local lifecycle signals, not hidden global messaging
SignalOperating-system request such as SIGTERMStop accepting work and release resources before exit

Professional workflow

Build the behavior in small, observable steps. Each step should leave something you can inspect or test.

  1. Describe the Node process boundary: inputs, outputs, state, timing, and expected failures.
  2. Implement the smallest correct path with names that expose intent.
  3. Add edge cases and failure handling before introducing abstractions.
  4. Verify behavior with realistic data and one deliberately adversarial example.
  5. Refactor only after the observable behavior is protected.

Make behavior observable

Before optimizing or abstracting, make inputs, outputs, state changes, timing, and failure paths visible. JavaScript becomes much easier to reason about when hidden work is exposed.

Guided code lab

Parse a focused CLI contract

The program validates arguments and sets a meaningful exit code on misuse.

course-cli.js
const [, , command, course] = process.argv;
if (command !== "open" || !course) {
  console.error("Usage: node course-cli.js open <course>");
  process.exitCode = 1;
} else {
  console.log("Opening " + course);
}

Shut down gracefully

Signal handling closes owned resources before allowing the process to end.

shutdown.js
let closing = false;
async function shutdown(signal) {
  if (closing) return;
  closing = true;
  console.log("Received", signal);
  await server.close();
}
process.on("SIGTERM", () => shutdown("SIGTERM"));
process.on("SIGINT", () => shutdown("SIGINT"));

Production practice

Contract

Make the Node process boundary explicit with validated inputs, structured outputs, owned resources, and stable failures.

Verification

Exercise normal work, invalid input, dependency failure, concurrency, and graceful cleanup in automated tests.

Operations

Use structured logs, health signals, timeouts, and configuration that can change without editing source code.

Common failure mode

Calling process.exit() during ordinary cleanup can terminate before buffered logs, responses, or writes complete.

Independent workshop

Build a course-report CLI that reads arguments, configuration, and emits JSON or human-readable output.

Your finished workshop must include:

  • Validated commands and exit codes
  • ES module organization
  • Signal-aware cleanup

Definition of done

Demonstrate the happy path and at least two edge cases, keep responsibilities separated, and add a short note explaining one design choice.

Recap & quick check

Key takeaways

  • Node adds server host APIs
  • The process is a boundary
  • Events are synchronous by default
  • Graceful shutdown protects in-flight work

Quick check

1. Where are CLI arguments exposed?

2. What is a safer validation failure than immediate process.exit()?

3. What commonly requests production shutdown?

Keep the workshop. Later modules deliberately build on these decisions, so each exercise can become part of your final portfolio architecture.