Theory
The word you have typed 3 times unexplained
const http = require('http');
You have now used that line in 2 lessons on faith. And meanwhile app.js is quietly growing: server code, seat arithmetic, soon file logging: one file collecting everything, the exact disease BCA403's packages cured in Java.
Both stories end in the same place: Node's module system: how code is split into reusable files, how require() fetches them, and how a file decides what it shows the world.
Theory
Modules and require(), formally
A module is a file of related code with a controlled public surface. require() loads one and returns its public object.
Two species, told apart by the argument's spelling:
- Built-in modules ship inside Node and load by bare name:
require('http'), and friendsfs(files: next lesson),url(query strings),path,os - User-defined modules are your own .js files and load by relative path:
require('./seats'): the./means this folder, and it is what tells Node "my file, not a package"
Practical
seats.js + app.js: create and include
// ---------- seats.js: a user-defined module ----------
exports.seatsLeft = function (booked, total) {
return total - booked; // PUBLIC: attached to exports
};
function auditLog(msg) { // PRIVATE: not exported,
// internal bookkeeping... // invisible outside this file
}
// ---------- app.js: including it ----------
// const seats = require('./seats'); // ./ = this folder
// console.log(seats.seatsLeft(310, 350)); // 40
// Simulated here so you can run the idea:
const seats = { seatsLeft: (booked, total) => total - booked };
console.log("Seats left: " + seats.seatsLeft(310, 350)); // 40
This example runs in Gri-Learn on the web, where you can edit it and see the output.
Theory
exports: the module's public counter
Inside a module, the exports object is the counter window: whatever you attach to it (exports.seatsLeft = ...) is servable to customers; every other function in the file stays in the back room.
require('./seats') hands the caller exactly that exports object, so seats.seatsLeft(310, 350) works and seats.auditLog(...) does not exist.
Recognise the idea? It is BCA403's access control reborn: exported = public members, unexported = private helpers: encapsulation at file scale, with ./seats playing the import statement.
Quiz
seats.js sits in the same folder as app.js, which says: const seats = require('seats'); What happens?
- Works: Node checks the current folder first
- Error: Cannot find module 'seats': a bare name makes Node look for built-ins and installed packages, not your files
- Works, but only functions attached to exports are loaded
- Node asks interactively which seats module you meant
Show the answer
Error: Cannot find module 'seats': a bare name makes Node look for built-ins and installed packages, not your files
The spelling IS the species: a bare name sends Node to its built-in list and the installed-packages folder, and finding no 'seats' there, it throws: your file was never consulted. The fix is 2 characters: require('./seats'): the relative path that says my folder, my file. This missing-dot-slash error is the single most common first-week Node bug, and exams echo it. Option C smuggles a true fact (only exports load) into the wrong verdict: the require fails before exports matter.
Think first
Design the split
FestConnect's server file is bloating: seat arithmetic, a fee calculator, the http server code. Propose the module layout: which files, what each exports, and what stays private: then tap.
Show the answer
Three files. seats.js exports seatsLeft (and later bookSeat); its validation helpers stay private. fees.js exports feeFor(event): the price table inside stays private, so changing prices touches one file. app.js exports nothing: it is the entry point, requiring http, ./seats and ./fees, and wiring them into createServer. The principle, identical to BCA403's packages: one topic per module, smallest possible public surface, and the entry file as thin conductor. That layout answer, with reasons, is full marks.
Watch out
Module slips
The missing ./: the quiz bug; built-ins and packages by name, YOUR files by path.
Forgetting to export: a perfectly good function that was never attached to exports comes back undefined at the call site: check the module's counter window first when a require'd function is missing.
The .js is optional: require('./seats') and require('./seats.js') both work; convention omits it.
Theory
The third telling of one story
Count the pattern's appearances in your BCA: Java's packages + import + public (BCA403), VB.NET's Friend/Public surfaces (BCA404), and now Node's modules + require + exports. Different spelling, same law: group related code, hide the plumbing, publish a small surface. Next lesson uses the built-in url module alongside http to finally READ what the visitor asked: query strings, split and served.
Summary
Key takeaways
- A module is a reusable code file; require() loads it and returns its public object.
- Built-ins load by bare name: http, fs, url, path, os.
- Your own files load by relative path: require('./seats'): the ./ is compulsory.
- exports is the public counter: attached functions are callable outside; the rest stays private.
- Missing ./ gives Cannot find module; missing exports gives undefined functions.
- Same organising law as BCA403 packages: small public surface, hidden plumbing.
- Memory hook: bare name for the shop-bought, dot-slash for the homemade.