All Cheatsheets

Node.js

Node.js

Node.js is a runtime that lets JavaScript run outside the browser, on servers and the command line. Before Node, JavaScript could only run inside a web browser; Node took Google Chrome's V8 engine and wrapped it with APIs for files, networking, and the operating system, so the same language can now power backends, tools, and desktop apps. It was created by Ryan Dahl in 2009.

Key Features -
  • V8 Engine : The core that compiles JavaScript straight to machine code, the same engine used in Chrome. Node adds a C++ layer (libuv) on top for I/O.
  • Single-Threaded : Node runs your JavaScript on one main thread, unlike traditional servers that spawn a new thread per request.
  • Non-Blocking & Event-Driven : Instead of waiting for slow operations (reading a file, a database query) to finish, Node starts them, continues with other work, and handles the result later through callbacks. This is what lets one thread serve thousands of connections.
  • Asynchronous : I/O operations run in the background and notify your code when done, so the server is never idle while waiting.
  • Fast : V8 plus non-blocking I/O makes Node very fast for network and I/O work.
  • Huge Ecosystem : The npm registry offers over a million ready-to-use packages.
  • One Language, Full Stack : The same JavaScript runs on both the front end and back end.
  • Cross-Platform : The same code runs on Windows, macOS, and Linux.
  • Scalable : The event-driven model handles many concurrent connections with little memory.
// hello.js -> run with: node hello.js console.log("Hello from Node.js"); console.log("Node version:", process.version);

How Node Works

Node handles a request by moving it through a pipeline: it takes user input, processes it, reads or writes storage as needed, and sends output back, all without blocking the single thread. The slow parts (database, files) run in the background while the thread serves other requests.

Request to Response Flow -
  • 1. Input : A client (browser, mobile app) sends an HTTP request to the server, for example POST /users with a JSON body.
  • 2. Event Queue : Node receives the request and places it on the event queue instead of handling it immediately.
  • 3. Event Loop : The event loop picks up the request. Simple work runs on the main thread; slow I/O (database, file) is handed off to libuv's background thread pool.
  • 4. Processing : Your code runs: routing decides which handler responds, middleware checks auth and validates the input, and business logic prepares the work.
  • 5. Store / Retrieve : If data is needed, Node queries a database or reads a file asynchronously. The thread does not wait; it serves other requests until the result arrives.
  • 6. Callback : When the I/O finishes, its callback (or resolved promise) is queued and the event loop resumes that request where it left off.
  • 7. Output : The handler builds a response (usually JSON) and sends it back to the client, completing the cycle.
Client Request -> Event Queue -> Event Loop --(slow I/O)--> Thread Pool (libuv) -> Process (routing, middleware, logic) -> Database / File (store or retrieve) -> Callback / Promise resolves -> Response back to Client

Event Loop & Async

The event loop is the heart of Node. Because JavaScript is single-threaded, Node cannot afford to sit and wait for slow I/O. It hands those operations off to the system, keeps running other code, and picks up the results when they are ready. This is why Node is excellent for I/O-heavy work but poor for heavy CPU computation, which would block the single thread.

  • Blocking vs Non-Blocking : A blocking call stops everything until it finishes; a non-blocking call returns immediately and notifies you later. Node's APIs are non-blocking by default.
  • Callbacks : The original async pattern: pass a function that runs when the operation completes. Nesting many callbacks leads to hard-to-read "callback hell".
  • Promises : An object representing a future value, chained with .then() and .catch(), which flattens nested callbacks.
  • async / await : Modern syntax that makes asynchronous code read like synchronous code, built on top of promises.
import { readFile } from "fs/promises"; async function load() { try { const data = await readFile("data.txt", "utf-8"); console.log(data); } catch (err) { console.error("Failed:", err.message); } } load();

Node Commands

Node ships with the node CLI for running scripts and an interactive REPL for quick experiments.

Running Code -
node app.js # run a script node # open the REPL (interactive shell) node --watch app.js # auto-restart on file changes (Node 18+) node --version # print installed version (also: node -v) node -e "console.log(2+2)" # run inline code node --inspect app.js # start with the debugger attached
REPL -

The REPL (Read-Eval-Print Loop) runs JavaScript line by line for testing snippets. Useful commands inside it: .help, .exit (or Ctrl+C twice), .save file.js, and .load file.js.

Environment & Scripts -
node index.js arg1 arg2 # args read via process.argv NODE_ENV=production node app.js # set an env variable (Linux/macOS) npm run dev # run a package.json script npx nodemon app.js # run a package without installing it
  • nodemon : A popular dev tool that watches files and restarts the app on every change, so you do not stop and rerun manually.

Modules

A module is a reusable piece of code in its own file. Node splits a program into modules and lets them share code through imports and exports. There are two module systems:

  • CommonJS (CJS) : Node's original system. Uses require() to import and module.exports to export. Loaded synchronously; still the default for many packages.
  • ES Modules (ESM) : The modern JavaScript standard, the same syntax used in browsers. Uses import and export. Enabled by setting "type": "module" in package.json or using the .mjs extension.
// CommonJS const fs = require("fs"); module.exports = { add }; // ES Modules import fs from "fs"; export function add(a, b) { return a + b; }
  • Local Modules : Your own files, imported by relative path (./utils.js).
  • Built-in / Core Modules : Shipped with Node, imported by name (fs, http).
  • Third-Party Modules : Installed from npm into node_modules, imported by package name (express).

Core Modules

Node ships with built-in modules that need no installation, covering the essentials of server-side work.

  • fs : Read, write, and manage files and directories.
  • http / https : Create web servers and make HTTP requests.
  • path : Work with file and directory paths across operating systems.
  • os : Get information about the operating system (CPU, memory, platform).
  • events : The EventEmitter class for building event-driven code.
  • crypto : Hashing, encryption, and generating secure random values.
  • stream : Process data piece by piece instead of loading it all into memory, ideal for large files.
  • url / querystring : Parse and build URLs and query parameters.
  • process : Info and control over the running Node process (environment variables, arguments, exit).
import http from "http"; const server = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("Hello World"); }); server.listen(3000, () => console.log("Running on port 3000"));

Globals & Environment

Node provides global objects available everywhere without importing, and a standard way to read configuration from the environment.

Global Objects -
  • global : The top-level object, like window in the browser.
  • process : The running Node process: process.argv (command-line arguments), process.env (environment variables), process.exit(), and process.cwd() (current directory).
  • __dirname / __filename : The absolute path of the current folder and file (available in CommonJS).
  • console : Logging: log, error, warn, table.
  • Buffer : Handles raw binary data, used with files and network streams.
  • setTimeout / setInterval / setImmediate : Schedule code to run later.
Environment Variables -

Secrets and config (database URLs, API keys, ports) are kept out of the code in environment variables, read through process.env. A .env file holds them locally and is loaded by the dotenv package (or Node's built-in --env-file flag). The .env file is never committed to Git.

# .env PORT=3000 DB_URL=postgres://localhost/mydb // app.js import "dotenv/config"; const port = process.env.PORT || 3000;
Error Handling -
  • Wrap await calls in try / catch, and use .catch() on promises.
  • In Express, pass errors to next(err) so a central error-handling middleware responds.
  • Catch process-level crashes with process.on("uncaughtException") and process.on("unhandledRejection").

Project Structure

Small scripts can be a single file, but real projects follow a layered structure that separates routing, business logic, and data access, so the codebase stays maintainable as it grows.

my-app/ ├── node_modules/ # installed packages (never committed) ├── src/ │ ├── controllers/ # handle requests, build responses │ ├── routes/ # map URLs to controllers │ ├── models/ # data shapes / database schemas │ ├── services/ # business logic │ ├── middleware/ # auth, logging, validation │ ├── config/ # database and app configuration │ └── app.js # sets up the server ├── tests/ # test files ├── public/ # static assets (images, css) ├── .env # environment variables (not committed) ├── .gitignore # lists node_modules, .env, etc. ├── package.json # manifest and scripts ├── package-lock.json # exact dependency versions └── index.js # entry point that starts the app
  • Separation of Concerns : Routes decide "where", controllers decide "what to do", services hold the actual logic, and models describe the data. Keeping them apart makes code easier to test and change.
  • .gitignore : Always excludes node_modules (recreated from the lock file) and .env (holds secrets).

Package Managers

A package manager downloads and manages the third-party libraries (packages) your project depends on, resolving their sub-dependencies and recording exact versions in a lock file so every install is reproducible. Packages live in the npm registry, the world's largest software registry.

  • npm : The default package manager, bundled with Node. Reliable and universal. Uses package-lock.json.
  • Yarn : Created by Meta to fix npm's early speed and reliability gaps. Introduced lock files and offline caching; still popular, especially Yarn's modern "Berry" versions.
  • pnpm : The efficient modern choice. Stores each package version once on disk and links it into projects, saving huge amounts of space and installing very fast. Strict about dependency access.
  • Bun : A package manager built into the Bun runtime, extremely fast, compatible with npm packages.
Setup & Info -
npm init # create package.json (interactive) npm init -y # create it with defaults npm --version # npm version (also: npm -v) npm list # list installed packages npm outdated # show packages with newer versions
Installing -
npm install # install everything in package.json npm install express # add a dependency (also: npm i) npm install -D nodemon # add a dev dependency (--save-dev) npm install -g nodemon # install globally (system-wide) npm install express@4.18.2 # install a specific version npm ci # clean install from lock file (CI/CD)
Updating & Removing -
npm update # update packages within allowed ranges npm update express # update a single package npm uninstall express # remove a package (also: npm remove) npm audit # scan dependencies for vulnerabilities npm audit fix # auto-fix vulnerabilities where possible
Running Scripts -
npm start # runs the "start" script npm test # runs the "test" script npm run dev # runs the "dev" script npm run build # runs the "build" script npx create-react-app app # run a package without installing it
  • npm Scripts : Any command in the "scripts" block of package.json is run with npm run <name>. The start and test names are special and skip the run word. dev and build are conventions, not built in: dev usually starts the app with live reload, and build compiles or bundles it for production.
  • npm version : npm version patch|minor|major bumps the version in package.json and creates a matching Git tag.
  • Dependencies vs devDependencies : Regular dependencies are needed to run the app in production (Express); dev dependencies are only needed while developing (test runners, linters, nodemon).
  • node_modules : The folder where installed packages live. It is never committed to Git; the lock file lets anyone recreate it with npm install.
  • Semantic Versioning : Versions read MAJOR.MINOR.PATCH (e.g. 4.18.2). ^ allows minor and patch updates, ~ allows only patch updates.

package.json

Every Node project has a package.json file at its root. It is the project's manifest: it records the name, version, scripts, and the exact list of dependencies, so the whole project can be shared and rebuilt from it.

{ "name": "my-app", "version": "1.0.0", "type": "module", "main": "index.js", "scripts": { "start": "node index.js", "dev": "nodemon index.js", "test": "jest" }, "dependencies": { "express": "^4.18.2" }, "devDependencies": { "nodemon": "^3.0.1" } }
  • scripts : Named shortcuts run with npm run <name>. start and test can be run without run.
  • main : The entry file loaded when the package is imported.
  • type : "module" enables ES Modules; omitted or "commonjs" uses CommonJS.

Frameworks

Node's core http module is low-level, so frameworks add routing, middleware, and structure on top of it. They fall into two broad groups: backend frameworks (build APIs and servers) and full-stack meta-frameworks (build entire websites, front and back).

Backend / API Frameworks -
  • Express : The minimal, most popular framework. Small core plus middleware; you assemble what you need. Great default for REST APIs and a huge ecosystem.
  • NestJS : An opinionated, structured framework using TypeScript, decorators, and dependency injection (Angular-style). Best for large, enterprise applications that need consistent architecture.
  • Fastify : Focused on speed and low overhead, with built-in schema validation. A modern, faster alternative to Express.
  • Koa : A lighter, more modern take on Express by the same team, built around async/await middleware.
  • Hapi : Configuration-driven framework with strong built-in features for larger teams.
Full-Stack Meta-Frameworks -
  • Next.js : React-based framework for full websites, with server-side rendering, static generation, and API routes. The most popular choice for production React apps.
  • Nuxt : The equivalent of Next.js for Vue.
  • SvelteKit / Remix : Full-stack frameworks for Svelte and React respectively, handling routing, data loading, and server rendering.
// minimal Express server import express from "express"; const app = express(); app.get("/", (req, res) => res.json({ message: "Hello API" })); app.listen(3000, () => console.log("API on port 3000"));

Node vs Other Runtimes

Node.js is a JavaScript runtime, but it is no longer the only one. Two newer runtimes aim to fix things Node got wrong or make it faster. They are alternatives to Node, not frameworks that run on it.

  • Node.js : The mature, default choice with the largest ecosystem and community. Uses the V8 engine. Added support for TypeScript, a test runner, and a --watch mode in recent versions.
  • Deno : Created by Node's original author to address its regrets. Secure by default (code must be granted file, network, and environment permissions), TypeScript built in, and web-standard APIs. Also uses V8.
  • Bun : An all-in-one runtime built for speed, using Apple's JavaScriptCore engine instead of V8. Bundles a package manager, bundler, and test runner in one tool, and runs most Node packages.
Node vs the Browser -
  • The browser has the window, document, and DOM; Node has global, process, and file-system access instead.
  • The browser sandboxes code away from the operating system; Node can read files, open network sockets, and run system commands.
  • Both run JavaScript on V8, which is why the language and much of the logic is shared between front and back end.

Uses

Node shines wherever the work is mostly waiting on input and output (network, files, databases) rather than crunching numbers, and wherever using one language across the whole stack is an advantage.

Great Fit -
  • REST & GraphQL APIs : The most common use, serving data to web and mobile clients.
  • Real-Time Apps : Chat, live notifications, collaborative tools, and multiplayer games using WebSockets, where Node's event-driven model excels.
  • Microservices : Small, fast-starting services that mostly pass data around.
  • Streaming : Handling large uploads, downloads, or media with streams.
  • CLI Tools & Build Tooling : Most front-end tooling (Webpack, Vite, ESLint) runs on Node.
  • Full-Stack JavaScript : Sharing types and logic between a React front end and a Node back end.
Poor Fit -
  • CPU-Heavy Work : Video encoding, complex image processing, or scientific computation would block the single thread. Languages like Go, Rust, or Python (with native libraries) suit these better, though Node can offload such work to worker threads.