Lab 08: Modules (CommonJS & ESM)

🎯 Objective

Master Node.js module systems — CommonJS (require/module.exports) and ES Modules (import/export), module resolution, and circular dependency avoidance.

⏱️ Estimated Time

30 minutes

📋 Prerequisites

  • Lab 7: Error Handling

🛠️ Tools Used

  • Node.js 20

🔬 Lab Instructions

Step 1: CommonJS Modules

const path = require("path");
const os = require("os");
const fs = require("fs");

// Built-in modules
console.log("Home:", os.homedir());
console.log("CPUs:", os.cpus().length);
console.log("Platform:", process.platform);
console.log("Node:", process.version);

// __dirname and __filename
console.log("Dir:", __dirname.slice(-20));

📸 Verified Output:

Step 2: Creating and Exporting Modules

📸 Verified Output:

Step 3: ES Modules Syntax (ESM)

📸 Verified Output:

Step 4: Module Pattern — Revealing Module

📸 Verified Output:

Step 5: Dynamic Imports

📸 Verified Output:

Step 6: package.json and npm

📸 Verified Output:

Step 7: Circular Dependency Detection

📸 Verified Output:

Step 8: Building a Module Index

📸 Verified Output:

✅ Verification

Expected output:

🚨 Common Mistakes

  1. module.exports = fn vs exports.fn = fn: exports is a reference to module.exports; exports = fn breaks the reference.

  2. Circular dependencies: A requires B which requires A — one gets a partial/empty module. Refactor to break cycles.

  3. ESM vs CJS mixing: .js files with type: "module" in package.json are ESM; use .cjs for CommonJS.

  4. require with relative path: Always use ./ prefix: require("./utils") not require("utils").

  5. Mutating cached modules: Node.js caches modules — mutations affect all importers.

📝 Summary

  • CJS: require() / module.exports — synchronous, cacheable, traditional Node.js

  • ESM: import/export — standard, supports tree-shaking, async capable

  • Module cache: Node.js loads each module once; subsequent require() returns cached object

  • Package.json: defines project metadata, scripts, and dependency versions

  • Dynamic import() for lazy loading; require() is synchronous and cannot be lazy

🔗 Further Reading

Last updated