Node.js and Express Backend Development Handbook
Express Framework Fundamentals
The Node.js web framework provides a structured pipeline from top to bottom:
- Routing system
- Middleware pipeline
- Response utilities
- Template integration (Pug, etc.)
The standard flow follows: Request → Middleware → Route → Response.
Middleware Pipeline
Middleware functions run before the final response. The function signature is (req, res, next). These functions can:
- Modify the req or res objects.
- Stop the request using
res.send(). - Pass control using
next().
Note: If neither next() nor res.send() is called, the request will hang. next() continues the flow, while res.send() ends the request lifecycle.
Routing and Request Handling
Routes are defined using app.METHOD(PATH, handler):
- app.get(): Read data
- app.post(): Send data
- app.put(): Update data
- app.delete(): Remove data
Route Priority Rules
Dynamic routes like /items/:id use parameters. A :param can match anything unless a more specific route is placed first in the code.
The Request and Response Objects
The Request object (req) contains incoming client data:
req.params: URL parameters (e.g.,/users/:id)req.query: Query strings (e.g.,?id=10)req.body: POST/PUT data (requires middleware). Note: GET requests usually do not have a body.
The Response object (res) is used to send output:
res.send(): Sends text or HTML.res.json(): Sends JSON data.res.render(): Compiles a Pug template into HTML.
Static Files and Pug Templates
Use app.use(express.static('public')) to serve CSS, images, and JS directly. This bypasses routes if a file exists.
Pug is a server-side template engine that converts .pug files to HTML. It runs only on the server. The rendering flow is: Route → res.render() → Pug compiles → HTML → Browser.
Pug Conditionals
Example: if user, p Welcome; else, p Login. These are evaluated on the server, so only one branch is sent to the client.
Asynchronous Programming and Node.js
Execution Order
The execution priority follows: Synchronous → Microtasks → Macrotasks.
Example pattern: console.log → Promise.then → setTimeout. Promises always run before setTimeout, even with a 0ms delay.
Promises and Async/Await
Promises have three states: pending, fulfilled, or rejected. Note: “Resolved” is not a formal technical state. A throw statement results in a rejection, and a .catch() block does not stop the chain.
Async/Await allows async functions to return a Promise and await to pause execution inside that function. This is not automatic parallel execution.
The Node.js Runtime Model
Node.js uses a single thread, an event loop, and non-blocking I/O. I/O tasks are delegated rather than blocked, but CPU parallelism is not automatic.
Core Modules and NPM
- HTTP Server: Created via
http.createServer. Missingres.end()causes the request to hang. - URL Module: Used to parse
req.url, which is not parsed automatically. - FS Module:
fs.promises.readFile()is asynchronous, whilefs.readFileSync()blocks execution. - Path Module: Handles cross-platform file paths using
joinandresolve.
NPM Versioning: The ^ symbol (e.g., "^4.17.1") allows minor and patch updates but prevents major version upgrades.
Database Integration with MongoDB
NoSQL vs Relational Databases
MongoDB is a NoSQL database that is non-relational and schema-less. Data is stored as BSON (JSON-like documents). The structure consists of Database → Collection → Document.
Mongoose ODM
Mongoose provides structure via Schemas and Models. A Model is the interface for a collection; Mongoose automatically pluralizes the model name (e.g., “Item” becomes “items”).
CRUD Operations
- Create:
const newItem = new Item({ name: "Book" }); await newItem.save(); - Read:
Item.find(),Item.findOne(), orItem.findById(). - Update:
Item.updateOne()orItem.updateMany()using operators like$inc. - Delete:
Item.deleteOne()orItem.deleteMany().
Modular Routing
To avoid a massive server.js file, use express.Router() to separate features into different files and attach them using app.use('/path', router).
User Authentication and Security
Authentication vs Authorization
Authentication verifies identity (login), while Authorization determines permissions. Authentication must always occur first.
Session-Based Authentication
The server creates a session and stores the Session ID in a client cookie. The session data stays on the server. Sessions are temporary and end upon logout or browser closure.
Token-Based Authentication (JWT)
This is a stateless method where the client stores a token and sends it with each request. JSON Web Tokens (JWT) are signed but not encrypted; the payload is readable via Base64, but integrity is maintained via the signature.
Password Security
Always use bcrypt for hashing. Hashing is a one-way process; never store plain-text passwords. Hash is not the same as encryption because it cannot be reversed.
Deployment Considerations
When deploying to platforms like Render:
- Use a GitHub repository.
- Set the start command to
node app.js. - Use
process.env.PORT || 3000for port binding. - Ensure
node_modulesand.envfiles are excluded from the upload.
