Node.js — Fundamentals
CommonJS: `require` and `module.exports`
Node's original module system. Every file is its own module — nothing is global by default, unlike a plain tag in a browser where everything shares one global scope. Code shares functionality by explicitly exporting it, and another file explicitly requires it.
require() runs synchronously and caches the result — requiring the same file twice returns the exact same cached object, not a fresh re-execution of the module. This is why mutating an object exported from a shared module affects every file that requires it — they're all holding a reference to the same cached instance.
ES Modules: `import`/`export`
Node also supports the standardized ES Module syntax — the same import/export syntax used in modern frontend code. It's opt-in: either name files .mjs, or set "type": "module" in package.json to make .js files use ES Modules by default.
A project picks one as its default and stays consistent — mixing them incorrectly (require()-ing an .mjs file directly, for instance) is a real, common source of confusing early errors. Check a package.json's "type" field first when debugging a module-related error in an unfamiliar codebase.
The `fs` module — reading and writing files
This is the first genuinely Node-specific capability: a browser cannot read an arbitrary file from disk for security reasons; Node can, because it's not sandboxed the way browser JavaScript is.
The sync/async distinction here is not a style preference — it's a real architectural decision. readFileSync blocks the single Node thread for the entire duration of the read, meaning every other request Node is handling has to wait behind it. readFile/fsPromises.readFile hand the work off and let Node keep serving other requests while the disk read completes in the background. Sync methods are fine for one-off scripts and startup-time config loading; they're a real production hazard inside a request handler.
The `path` module — building paths that work everywhere
Windows uses \ as a path separator; Linux and macOS use /. Hardcoding either one breaks on the other operating system. path builds paths correctly regardless of platform.
__dirname (CommonJS) points to the directory of the current file — using it with path.join is the standard, reliable way to reference a file relative to your source code, rather than relative to whatever directory node happened to be invoked from.
Building a basic HTTP server with the built-in `http` module
This is the module every backend framework (Express included) is ultimately built on top of.
Every piece of routing logic here — matching the URL, checking the method, sending the right status code — is something Express does for you with a much shorter syntax (app.get("/", handler)). Seeing it done manually first is exactly what makes Express's abstraction click later, instead of feeling like unexplained magic.
`process` and environment variables
process is a global object (available in every Node file, no require needed) representing the currently running Node process itself.
Reading configuration from process.env rather than hardcoding it is the standard way a Node application adapts to different environments without changing code — the same code runs in dev and production, with different environment variables supplying the difference. .env files as a convenient way to set those variables locally are covered in Intermediate.
npm and `package.json` basics
dependencies are needed for the app to actually run; devDependencies are only needed while developing (a test runner, a dev-mode auto-restart tool like nodemon). This distinction matters in production — a production install can skip devDependencies entirely (npm ci --omit=dev), keeping the deployed footprint smaller.
Try It (2 Minutes)
Create info.js:
Run it with node info.js. Every value printed came from Node's built-in modules querying the actual machine it's running on — none of this is possible from browser JavaScript, which has no access to the operating system underneath it. That's the concrete, practical difference between "JavaScript in a browser" and "JavaScript in Node."

