Node.js Modules Quiz: npm, Streams and Process Practice Test
Test your Node.js with 12 questions and three programs on CommonJS and ES modules, npm and semver, core modules, streams and backpressure, and processes.
- Course: JavaScript study plan
- Module: Modules and Node
- Kind: Checkpoint — cleared at 70%
- Reading time: 24 min
- Runtime: Node 16
Checkpoint — Modules and Node is the checkpoint that closes the Modules and Node module: a graded quiz and whole-program exercises, passed at 70%.
Instructions
This checkpoint covers CommonJS versus ES modules (loading, caching, copies versus live bindings, module type detection, interop, cycles, dynamic import()), package.json fields, the resolution algorithm, semver ranges and lockfiles, the core modules (path, fs, process, events, url, crypto), Buffer and streams with pipeline and backpressure, and the process surface — arguments, environment, exit codes, signals, child processes and workers.
How it works. Twelve questions and three programs; 70% on the questions and every program accepted clears the module.
Before you start, make sure you can answer:
- How Node decides whether a
.jsfile is CJS or ESM; why ESM imports need extensions; what a live binding is; what CJS does on a circularrequire. - The three steps of resolving
require("x");^versus~and what^0.xmeans; whynpm ciand a committed lockfile. path.joinversusresolve; the threefsstyles; whatemit("error")with no listener does;exitCodeversusexit().- Why
pipelinebeatspipe; what backpressure is; whychunk.toString()per chunk breaks on UTF-8. execversusexecFile/spawn; what aSIGTERMhandler must do; when to useworker_threads.
The programs are a module-graph loader that reproduces CommonJS load order and detects cycles, a stream pipeline that parses and summarises log lines with a Transform in object mode, and a configuration CLI that merges flags, environment and defaults with the standard precedence.
Common questions
What does CommonJS do on a circular require?
It returns the partially filled exports of the module that is still loading, often an empty object, so the module that asked sees undefined for anything defined later. The failure is silent, which is why the fix is to break the cycle by moving the shared code into a third module.
Why does chunk.toString() break UTF-8 text in a stream?
A chunk boundary can fall in the middle of a multi-byte UTF-8 character, so decoding each chunk separately produces garbage at the seams. Call setEncoding("utf8") on the stream, use a StringDecoder, which buffers partial characters, or collect the buffers and decode once with Buffer.concat.
What must a SIGTERM handler do in Node.js?
Stop accepting new work, finish or fail in-flight work quickly, close connections and flush logs, then call process.exit. Installing the handler replaces Node's default exit, so a handler that forgets to exit can leave the process running until the grace period ends and the orchestrator sends an uncatchable SIGKILL.
Exercises
Load a module graph the CommonJS way
Lines module <name>: <dep> <dep>… declare modules and what they require (in order); entry <name> names the entry point. Simulate CommonJS loading from the entry: a module is marked loading, pushed on the stack and recorded in the start order; each dependency is required in turn — a loaded module is a cache hit, a loading one is a cycle recorded as a -> b -> a (the stack from the repeated module, plus it) and returns its partial exports, an undeclared one is recorded as missing; then the module is marked loaded and recorded in the finish order. Print start: …, finish: …, cycles: <"; "-joined or none>, missing: <names or none> unused: <declared modules never loaded, or none>.
Example:
module app: config db routes
module config:
module db: config logger
module logger: config
module routes: db handlers
module handlers: routes
module unused: config
entry app
→
start: app config db logger routes handlers
finish: config logger db handlers routes app
cycles: routes -> handlers -> routes
missing: none unused: unusedA log-summarising stream pipeline
Line 1 is the minimum level; each following line is <ISO time> <LEVEL> <message>. Build a pipeline of Readable.from(lines) → a parsing Transform (readable object mode; a line that does not match ^(\S+)\s+(DEBUG|INFO|WARN|ERROR)\s+(.*)$ is counted as malformed and dropped) → a filtering Transform (keep levels ≥ minimum) → a summarising object-mode Writable that counts per level, per hour (characters 11–12 of the time), and remembers the first ERROR. Print seen=<lines> malformed=<n> kept=<n>, levels: <LEVEL=n in DEBUG,INFO,WARN,ERROR order, or none>, byHour: <HHh=n sorted, or none>, firstError: <time message or none>.
Example: WARN and five log lines including one garbage line →
seen=6 malformed=1 kept=3
levels: WARN=1 ERROR=2
byHour: 10h=1 11h=2
firstError: 2024-01-01T10:16:00Z db timeoutA configuration CLI: flag > env > default
Defaults are { port: 3000, host: "localhost", debug: false, workers: 1 }, read from the environment as APP_PORT, APP_HOST, APP_DEBUG, APP_WORKERS. Line 1 of the input is the argv (possibly blank) — only --key=value, --flag (true) and --no-flag (false) matter; the following lines are KEY=VALUE environment entries. For each key take the flag, else the env value, else the default, coercing to the default's type (integers for numbers; true/1/false/0 for booleans; anything else is a TypeError("<key> must be an integer, got <JSON>")/("<key> must be true/false, got <JSON>")). Validate port 1–65535 and workers ≥ 1. Print config=<JSON> and sources: <key=flag|env|default …> and wouldExitWith=0, or invalid: <messages joined by "; "> and wouldExitWith=1.
Example: --port=8080 --debug then APP_HOST=0.0.0.0, APP_WORKERS=4, APP_PORT=9999 →
config={"port":8080,"host":"0.0.0.0","debug":true,"workers":4}
sources: port=flag host=env debug=flag workers=env
wouldExitWith=0
The flag beats APP_PORT; --workers=0 --port=70000 → invalid: port must be 1-65535, got 70000; workers must be at least 1, got 0.
In this module: Modules and Node
- CommonJS and ES modules — two module systems, one runtime
- Packages, package.json, npm and semver
- The core modules you use every week — fs, path, os, process, util, events, url, crypto
- Buffers and streams — bytes, and data that does not fit in memory
- The process — arguments, environment, exit codes, signals, child processes and workers
- Checkpoint — Modules and Node (this lesson)
← The process — arguments, environment, exit codes, signals, child processes and workers · Unicode and how JavaScript strings really work →