Node.js • Chapter 4 • Beginner Friendly
CommonJS Modules
Learn this chapter by understanding what each Node.js feature does, when to use it, how it can fail, and how to verify the result.
4.1 Using require
Using require is part of Chapter 4, “CommonJS Modules.” For a beginner, the first goal is to understand the observable behavior before memorizing an API. In this lesson, module means a file or package boundary used to organize and share code. The practical focus is inputs, observable output, error behavior, and the resource that the operation consumes.
Start from the smallest working behavior and name every input and output. In Chapter 4 (CommonJS Modules), for Using require, write down what enters the operation, what Node.js is expected to do, and what the caller can observe afterward. If the result is asynchronous, also state when completion is known and where errors travel.
For Using require in Chapter 4, the mechanism to keep in mind is explicit imports, exports, package metadata, and predictable dependency boundaries. A good experiment changes one thing at a time and checks both success and failure. When you finish this topic, you should be able to explain why the code works, not only copy the syntax.
Key terms in plain language
- module — a file or package boundary used to organize and share code.
- require — a concrete part of using require that the lesson isolates so you can see its effect instead of treating the whole feature as a black box.
10 teaching examples
Example 1: Real service scenario
Imagine a small tutoring-service backend applying Using require during Chapter 4 (CommonJS Modules). State what arrives from the caller, what the Node.js process must do, what it returns, and what must be logged if the operation fails.
Example 2: Security or trust check
In the CommonJS Modules context, treat one value used by Using require as untrusted. Identify what must be validated, encoded, bounded, or refused before the value reaches a sensitive operation. Explain the consequence of trusting it blindly.
Example 3: Concurrency check
For Chapter 4, run or reason about two Using require operations close together. Ask whether ordering matters, whether shared state can conflict, and whether work should be awaited, queued, streamed, or moved to another worker.
Example 4: Performance check
While studying CommonJS Modules, measure the resource most affected by Using require: elapsed time, bytes, memory, open connections, event-loop delay, or database round trips. Optimize only after the measurement identifies a meaningful cost.
Example 5: Refactoring example
In a CommonJS Modules exercise, take code that mixes Using require with unrelated business logic and split it into a small function with an explicit input and return value. The caller should not need to know low-level details unless they are part of the contract.
Example 6: Production reasoning
Assume the Using require code from Chapter 4 runs thousands of times. Decide what needs a timeout, limit, retry rule, cleanup step, metric, or graceful-shutdown hook. The goal is predictable behavior under repetition, load, and partial failure.
Example 7: Minimal working case
In Chapter 4 (CommonJS Modules), build the smallest Using require example that has one clear input and one visible result. Before running it, write what you expect to happen. Then verify inputs, observable output, error behavior, and the resource that the operation consumes. This establishes a baseline you can reason about.
Example 8: Change one input
For Chapter 4 (CommonJS Modules), keep the same program but change exactly one input related to Using require. Compare the two outputs and explain why the change happened. This teaches cause and effect instead of memorizing syntax.
Example 9: Compare two approaches
Within CommonJS Modules, solve one tiny task twice: first with the most direct approach to Using require, then with a reasonable alternative. Compare readability, error behavior, and resource use. Choose the version whose tradeoff matches the task.
Example 10: Failure you can recognize
For CommonJS Modules, create a safe failure involving Using require, such as invalid data, a missing resource, a closed connection, or a rejected promise. Observe the error type and decide where the program should handle it rather than hiding it.
Node.js coding example
// Topic: Using require
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const here = path.dirname(fileURLToPath(import.meta.url));
const file = path.join(here, 'chapter-4.json');
console.log(path.basename(file), path.isAbsolute(file));Step-by-step code explanation
- Import built-in modules with the node: prefix.
- Convert import.meta.url to a local file-system path.
- Join path segments without hard-coding separators.
- Inspect the basename and whether the result is absolute.
Expected output: chapter-4.json true
Practice exercise
Build a small Chapter 4 example for Using require. Write the expected result before running it. Add one failure case, then change exactly one condition and explain why the behavior changed. For production reasoning, identify one limit, timeout, cleanup step, or validation rule that would make the code safer.
4.2 Exporting with module.exports
Exporting with module.exports is part of Chapter 4, “CommonJS Modules.” For a beginner, the first goal is to understand the observable behavior before memorizing an API. In this lesson, module means a file or package boundary used to organize and share code. The practical focus is module format, resolution rules, cache behavior, and public API boundaries.
Compare the correct approach with a common alternative so the tradeoff is visible. In Chapter 4 (CommonJS Modules), the useful comparison for Exporting with module.exports is not “short code versus long code”; it is predictable behavior versus hidden assumptions. Check platform differences, lifetime of resources, and whether the caller must wait for completion.
For Exporting with module.exports in Chapter 4, the mechanism to keep in mind is explicit imports, exports, package metadata, and predictable dependency boundaries. A good experiment changes one thing at a time and checks both success and failure. When you finish this topic, you should be able to explain why the code works, not only copy the syntax.
Key terms in plain language
- module — a file or package boundary used to organize and share code.
- Exporting — a concrete part of exporting with module.exports that the lesson isolates so you can see its effect instead of treating the whole feature as a black box.
- module.exports — a concrete part of exporting with module.exports that the lesson isolates so you can see its effect instead of treating the whole feature as a black box.
10 teaching examples
Example 1: Concurrency check
For Chapter 4, run or reason about two Exporting with module.exports operations close together. Ask whether ordering matters, whether shared state can conflict, and whether work should be awaited, queued, streamed, or moved to another worker.
Example 2: Performance check
While studying CommonJS Modules, measure the resource most affected by Exporting with module.exports: elapsed time, bytes, memory, open connections, event-loop delay, or database round trips. Optimize only after the measurement identifies a meaningful cost.
Example 3: Refactoring example
In a CommonJS Modules exercise, take code that mixes Exporting with module.exports with unrelated business logic and split it into a small function with an explicit input and return value. The caller should not need to know low-level details unless they are part of the contract.
Example 4: Production reasoning
Assume the Exporting with module.exports code from Chapter 4 runs thousands of times. Decide what needs a timeout, limit, retry rule, cleanup step, metric, or graceful-shutdown hook. The goal is predictable behavior under repetition, load, and partial failure.
Example 5: Minimal working case
In Chapter 4 (CommonJS Modules), build the smallest Exporting with module.exports example that has one clear input and one visible result. Before running it, write what you expect to happen. Then verify module format, resolution rules, cache behavior, and public API boundaries. This establishes a baseline you can reason about.
Example 6: Change one input
For Chapter 4 (CommonJS Modules), keep the same program but change exactly one input related to Exporting with module.exports. Compare the two outputs and explain why the change happened. This teaches cause and effect instead of memorizing syntax.
Example 7: Compare two approaches
Within CommonJS Modules, solve one tiny task twice: first with the most direct approach to Exporting with module.exports, then with a reasonable alternative. Compare readability, error behavior, and resource use. Choose the version whose tradeoff matches the task.
Example 8: Failure you can recognize
For CommonJS Modules, create a safe failure involving Exporting with module.exports, such as invalid data, a missing resource, a closed connection, or a rejected promise. Observe the error type and decide where the program should handle it rather than hiding it.
Example 9: Real service scenario
Imagine a small tutoring-service backend applying Exporting with module.exports during Chapter 4 (CommonJS Modules). State what arrives from the caller, what the Node.js process must do, what it returns, and what must be logged if the operation fails.
Example 10: Security or trust check
In the CommonJS Modules context, treat one value used by Exporting with module.exports as untrusted. Identify what must be validated, encoded, bounded, or refused before the value reaches a sensitive operation. Explain the consequence of trusting it blindly.
Node.js coding example
// Topic: Exporting with module.exports
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const here = path.dirname(fileURLToPath(import.meta.url));
const file = path.join(here, 'chapter-4.json');
console.log(path.basename(file), path.isAbsolute(file));Step-by-step code explanation
- Import built-in modules with the node: prefix.
- Convert import.meta.url to a local file-system path.
- Join path segments without hard-coding separators.
- Inspect the basename and whether the result is absolute.
Expected output: chapter-4.json true
Practice exercise
Build a small Chapter 4 example for Exporting with module.exports. Write the expected result before running it. Add one failure case, then change exactly one condition and explain why the behavior changed. For production reasoning, identify one limit, timeout, cleanup step, or validation rule that would make the code safer.
4.3 How CommonJS Module Resolution Works
How CommonJS Module Resolution Works is part of Chapter 4, “CommonJS Modules.” For a beginner, the first goal is to understand the observable behavior before memorizing an API. In this lesson, module means a file or package boundary used to organize and share code. The practical focus is module format, resolution rules, cache behavior, and public API boundaries.
Deliberately inspect a failure case because error behavior is part of the API. In Chapter 4 (CommonJS Modules), a robust understanding of How CommonJS Module Resolution Works includes its failure path. Ask what happens with missing data, invalid input, a closed resource, cancellation, or partial completion. Handling those cases deliberately is part of correct Node.js design.
For How CommonJS Module Resolution Works in Chapter 4, the mechanism to keep in mind is explicit imports, exports, package metadata, and predictable dependency boundaries. A good experiment changes one thing at a time and checks both success and failure. When you finish this topic, you should be able to explain why the code works, not only copy the syntax.
Key terms in plain language
- module — a file or package boundary used to organize and share code.
- CommonJS — a concrete part of how commonjs module resolution works that the lesson isolates so you can see its effect instead of treating the whole feature as a black box.
- Resolution — a concrete part of how commonjs module resolution works that the lesson isolates so you can see its effect instead of treating the whole feature as a black box.
10 teaching examples
Example 1: Refactoring example
In a CommonJS Modules exercise, take code that mixes How CommonJS Module Resolution Works with unrelated business logic and split it into a small function with an explicit input and return value. The caller should not need to know low-level details unless they are part of the contract.
Example 2: Production reasoning
Assume the How CommonJS Module Resolution Works code from Chapter 4 runs thousands of times. Decide what needs a timeout, limit, retry rule, cleanup step, metric, or graceful-shutdown hook. The goal is predictable behavior under repetition, load, and partial failure.
Example 3: Minimal working case
In Chapter 4 (CommonJS Modules), build the smallest How CommonJS Module Resolution Works example that has one clear input and one visible result. Before running it, write what you expect to happen. Then verify module format, resolution rules, cache behavior, and public API boundaries. This establishes a baseline you can reason about.
Example 4: Change one input
For Chapter 4 (CommonJS Modules), keep the same program but change exactly one input related to How CommonJS Module Resolution Works. Compare the two outputs and explain why the change happened. This teaches cause and effect instead of memorizing syntax.
Example 5: Compare two approaches
Within CommonJS Modules, solve one tiny task twice: first with the most direct approach to How CommonJS Module Resolution Works, then with a reasonable alternative. Compare readability, error behavior, and resource use. Choose the version whose tradeoff matches the task.
Example 6: Failure you can recognize
For CommonJS Modules, create a safe failure involving How CommonJS Module Resolution Works, such as invalid data, a missing resource, a closed connection, or a rejected promise. Observe the error type and decide where the program should handle it rather than hiding it.
Example 7: Real service scenario
Imagine a small tutoring-service backend applying How CommonJS Module Resolution Works during Chapter 4 (CommonJS Modules). State what arrives from the caller, what the Node.js process must do, what it returns, and what must be logged if the operation fails.
Example 8: Security or trust check
In the CommonJS Modules context, treat one value used by How CommonJS Module Resolution Works as untrusted. Identify what must be validated, encoded, bounded, or refused before the value reaches a sensitive operation. Explain the consequence of trusting it blindly.
Example 9: Concurrency check
For Chapter 4, run or reason about two How CommonJS Module Resolution Works operations close together. Ask whether ordering matters, whether shared state can conflict, and whether work should be awaited, queued, streamed, or moved to another worker.
Example 10: Performance check
While studying CommonJS Modules, measure the resource most affected by How CommonJS Module Resolution Works: elapsed time, bytes, memory, open connections, event-loop delay, or database round trips. Optimize only after the measurement identifies a meaningful cost.
Node.js coding example
// Topic: How CommonJS Module Resolution Works
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const here = path.dirname(fileURLToPath(import.meta.url));
const file = path.join(here, 'chapter-4.json');
console.log(path.basename(file), path.isAbsolute(file));Step-by-step code explanation
- Import built-in modules with the node: prefix.
- Convert import.meta.url to a local file-system path.
- Join path segments without hard-coding separators.
- Inspect the basename and whether the result is absolute.
Expected output: chapter-4.json true
Practice exercise
Build a small Chapter 4 example for How CommonJS Module Resolution Works. Write the expected result before running it. Add one failure case, then change exactly one condition and explain why the behavior changed. For production reasoning, identify one limit, timeout, cleanup step, or validation rule that would make the code safer.
4.4 The Module Cache
The Module Cache is part of Chapter 4, “CommonJS Modules.” For a beginner, the first goal is to understand the observable behavior before memorizing an API. In this lesson, module means a file or package boundary used to organize and share code. The practical focus is cache keys, freshness, expiration, invalidation, and stampede risk.
Connect the idea to a small service or automation task that a learner could actually build. In Chapter 4 (CommonJS Modules), connect The Module Cache to a small backend, automation script, or command-line tool. That makes the API easier to remember because each method call has a reason, a boundary, and an expected result.
For The Module Cache in Chapter 4, the mechanism to keep in mind is explicit imports, exports, package metadata, and predictable dependency boundaries. A good experiment changes one thing at a time and checks both success and failure. When you finish this topic, you should be able to explain why the code works, not only copy the syntax.
Key terms in plain language
- module — a file or package boundary used to organize and share code.
- Cache — a concrete part of the module cache that the lesson isolates so you can see its effect instead of treating the whole feature as a black box.
10 teaching examples
Example 1: Minimal working case
In Chapter 4 (CommonJS Modules), build the smallest The Module Cache example that has one clear input and one visible result. Before running it, write what you expect to happen. Then verify cache keys, freshness, expiration, invalidation, and stampede risk. This establishes a baseline you can reason about.
Example 2: Change one input
For Chapter 4 (CommonJS Modules), keep the same program but change exactly one input related to The Module Cache. Compare the two outputs and explain why the change happened. This teaches cause and effect instead of memorizing syntax.
Example 3: Compare two approaches
Within CommonJS Modules, solve one tiny task twice: first with the most direct approach to The Module Cache, then with a reasonable alternative. Compare readability, error behavior, and resource use. Choose the version whose tradeoff matches the task.
Example 4: Failure you can recognize
For CommonJS Modules, create a safe failure involving The Module Cache, such as invalid data, a missing resource, a closed connection, or a rejected promise. Observe the error type and decide where the program should handle it rather than hiding it.
Example 5: Real service scenario
Imagine a small tutoring-service backend applying The Module Cache during Chapter 4 (CommonJS Modules). State what arrives from the caller, what the Node.js process must do, what it returns, and what must be logged if the operation fails.
Example 6: Security or trust check
In the CommonJS Modules context, treat one value used by The Module Cache as untrusted. Identify what must be validated, encoded, bounded, or refused before the value reaches a sensitive operation. Explain the consequence of trusting it blindly.
Example 7: Concurrency check
For Chapter 4, run or reason about two The Module Cache operations close together. Ask whether ordering matters, whether shared state can conflict, and whether work should be awaited, queued, streamed, or moved to another worker.
Example 8: Performance check
While studying CommonJS Modules, measure the resource most affected by The Module Cache: elapsed time, bytes, memory, open connections, event-loop delay, or database round trips. Optimize only after the measurement identifies a meaningful cost.
Example 9: Refactoring example
In a CommonJS Modules exercise, take code that mixes The Module Cache with unrelated business logic and split it into a small function with an explicit input and return value. The caller should not need to know low-level details unless they are part of the contract.
Example 10: Production reasoning
Assume the The Module Cache code from Chapter 4 runs thousands of times. Decide what needs a timeout, limit, retry rule, cleanup step, metric, or graceful-shutdown hook. The goal is predictable behavior under repetition, load, and partial failure.
Node.js coding example
// Topic: The Module Cache
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const here = path.dirname(fileURLToPath(import.meta.url));
const file = path.join(here, 'chapter-4.json');
console.log(path.basename(file), path.isAbsolute(file));Step-by-step code explanation
- Import built-in modules with the node: prefix.
- Convert import.meta.url to a local file-system path.
- Join path segments without hard-coding separators.
- Inspect the basename and whether the result is absolute.
Expected output: chapter-4.json true
Practice exercise
Build a small Chapter 4 example for The Module Cache. Write the expected result before running it. Add one failure case, then change exactly one condition and explain why the behavior changed. For production reasoning, identify one limit, timeout, cleanup step, or validation rule that would make the code safer.
4.5 __dirname __filename and Module Paths
__dirname __filename and Module Paths is part of Chapter 4, “CommonJS Modules.” For a beginner, the first goal is to understand the observable behavior before memorizing an API. In this lesson, module means a file or package boundary used to organize and share code. The practical focus is module format, resolution rules, cache behavior, and public API boundaries.
Finish by asking what changes when the code runs repeatedly, concurrently, or with untrusted input. In Chapter 4 (CommonJS Modules), production code using __dirname __filename and Module Paths should be reviewable by another developer. Keep responsibilities small, add limits around untrusted or repeated work, and record enough context to diagnose failures without exposing secrets.
For __dirname __filename and Module Paths in Chapter 4, the mechanism to keep in mind is explicit imports, exports, package metadata, and predictable dependency boundaries. A good experiment changes one thing at a time and checks both success and failure. When you finish this topic, you should be able to explain why the code works, not only copy the syntax.
Key terms in plain language
- module — a file or package boundary used to organize and share code.
- dirname — a concrete part of __dirname __filename and module paths that the lesson isolates so you can see its effect instead of treating the whole feature as a black box.
- filename — a concrete part of __dirname __filename and module paths that the lesson isolates so you can see its effect instead of treating the whole feature as a black box.
10 teaching examples
Example 1: Compare two approaches
Within CommonJS Modules, solve one tiny task twice: first with the most direct approach to __dirname __filename and Module Paths, then with a reasonable alternative. Compare readability, error behavior, and resource use. Choose the version whose tradeoff matches the task.
Example 2: Failure you can recognize
For CommonJS Modules, create a safe failure involving __dirname __filename and Module Paths, such as invalid data, a missing resource, a closed connection, or a rejected promise. Observe the error type and decide where the program should handle it rather than hiding it.
Example 3: Real service scenario
Imagine a small tutoring-service backend applying __dirname __filename and Module Paths during Chapter 4 (CommonJS Modules). State what arrives from the caller, what the Node.js process must do, what it returns, and what must be logged if the operation fails.
Example 4: Security or trust check
In the CommonJS Modules context, treat one value used by __dirname __filename and Module Paths as untrusted. Identify what must be validated, encoded, bounded, or refused before the value reaches a sensitive operation. Explain the consequence of trusting it blindly.
Example 5: Concurrency check
For Chapter 4, run or reason about two __dirname __filename and Module Paths operations close together. Ask whether ordering matters, whether shared state can conflict, and whether work should be awaited, queued, streamed, or moved to another worker.
Example 6: Performance check
While studying CommonJS Modules, measure the resource most affected by __dirname __filename and Module Paths: elapsed time, bytes, memory, open connections, event-loop delay, or database round trips. Optimize only after the measurement identifies a meaningful cost.
Example 7: Refactoring example
In a CommonJS Modules exercise, take code that mixes __dirname __filename and Module Paths with unrelated business logic and split it into a small function with an explicit input and return value. The caller should not need to know low-level details unless they are part of the contract.
Example 8: Production reasoning
Assume the __dirname __filename and Module Paths code from Chapter 4 runs thousands of times. Decide what needs a timeout, limit, retry rule, cleanup step, metric, or graceful-shutdown hook. The goal is predictable behavior under repetition, load, and partial failure.
Example 9: Minimal working case
In Chapter 4 (CommonJS Modules), build the smallest __dirname __filename and Module Paths example that has one clear input and one visible result. Before running it, write what you expect to happen. Then verify module format, resolution rules, cache behavior, and public API boundaries. This establishes a baseline you can reason about.
Example 10: Change one input
For Chapter 4 (CommonJS Modules), keep the same program but change exactly one input related to __dirname __filename and Module Paths. Compare the two outputs and explain why the change happened. This teaches cause and effect instead of memorizing syntax.
Node.js coding example
// Topic: __dirname __filename and Module Paths
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const here = path.dirname(fileURLToPath(import.meta.url));
const file = path.join(here, 'chapter-4.json');
console.log(path.basename(file), path.isAbsolute(file));Step-by-step code explanation
- Import built-in modules with the node: prefix.
- Convert import.meta.url to a local file-system path.
- Join path segments without hard-coding separators.
- Inspect the basename and whether the result is absolute.
Expected output: chapter-4.json true
Practice exercise
Build a small Chapter 4 example for __dirname __filename and Module Paths. Write the expected result before running it. Add one failure case, then change exactly one condition and explain why the behavior changed. For production reasoning, identify one limit, timeout, cleanup step, or validation rule that would make the code safer.
Chapter 4 review — 20 questions and answers
1. What is the main purpose of Using require?
Answer: Its purpose is to make Using require explicit and observable so the program can use it predictably rather than relying on hidden assumptions.
2. What should a beginner identify before using Using require?
Answer: Identify the input, expected output, completion signal, possible error, and any resource that must be released.
3. Why is error handling important for Using require?
Answer: Because real inputs and resources fail. Correct code defines how the failure is reported and what cleanup still must happen.
4. How can you test Using require safely?
Answer: Start with a tiny deterministic case, test one failure case, then add concurrency or untrusted input only after the baseline is understood.
5. What is the main purpose of Exporting with module.exports?
Answer: Its purpose is to make Exporting with module.exports explicit and observable so the program can use it predictably rather than relying on hidden assumptions.
6. What should a beginner identify before using Exporting with module.exports?
Answer: Identify the input, expected output, completion signal, possible error, and any resource that must be released.
7. Why is error handling important for Exporting with module.exports?
Answer: Because real inputs and resources fail. Correct code defines how the failure is reported and what cleanup still must happen.
8. How can you test Exporting with module.exports safely?
Answer: Start with a tiny deterministic case, test one failure case, then add concurrency or untrusted input only after the baseline is understood.
9. What is the main purpose of How CommonJS Module Resolution Works?
Answer: Its purpose is to make How CommonJS Module Resolution Works explicit and observable so the program can use it predictably rather than relying on hidden assumptions.
10. What should a beginner identify before using How CommonJS Module Resolution Works?
Answer: Identify the input, expected output, completion signal, possible error, and any resource that must be released.
11. Why is error handling important for How CommonJS Module Resolution Works?
Answer: Because real inputs and resources fail. Correct code defines how the failure is reported and what cleanup still must happen.
12. How can you test How CommonJS Module Resolution Works safely?
Answer: Start with a tiny deterministic case, test one failure case, then add concurrency or untrusted input only after the baseline is understood.
13. What is the main purpose of The Module Cache?
Answer: Its purpose is to make The Module Cache explicit and observable so the program can use it predictably rather than relying on hidden assumptions.
14. What should a beginner identify before using The Module Cache?
Answer: Identify the input, expected output, completion signal, possible error, and any resource that must be released.
15. Why is error handling important for The Module Cache?
Answer: Because real inputs and resources fail. Correct code defines how the failure is reported and what cleanup still must happen.
16. How can you test The Module Cache safely?
Answer: Start with a tiny deterministic case, test one failure case, then add concurrency or untrusted input only after the baseline is understood.
17. What is the main purpose of __dirname __filename and Module Paths?
Answer: Its purpose is to make __dirname __filename and Module Paths explicit and observable so the program can use it predictably rather than relying on hidden assumptions.
18. What should a beginner identify before using __dirname __filename and Module Paths?
Answer: Identify the input, expected output, completion signal, possible error, and any resource that must be released.
19. Why is error handling important for __dirname __filename and Module Paths?
Answer: Because real inputs and resources fail. Correct code defines how the failure is reported and what cleanup still must happen.
20. How can you test __dirname __filename and Module Paths safely?
Answer: Start with a tiny deterministic case, test one failure case, then add concurrency or untrusted input only after the baseline is understood.