Grokking ExpressJS
Vote

0% completed

​

What is Express.js and Why Use It?

What Express Did for You

Express Runs on Top of the http Module

Why Developers Choose Express

What It Costs

Which Version This Course Uses

The two programs below do the same job. Each one keeps a list of tasks in memory, returns the list for GET /tasks, and adds a task for POST /tasks. The first uses only the http module that ships with Node.js:

const http = require('node:http'); const tasks = [{ id: 1, title: 'Write the README', done: false }]; const server = http.createServer((req, res) => { const url = new URL(req.url, `http://${req.headers.host}`); if (req.method === 'GET' && url.pathname === '/tasks') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(tasks)); return; } if (req.method === 'POST' && url.pathname === '/tasks') { let body = ''; req.on('data', (chunk) => { body += chunk; }); req.on('end', () => { let data; try { data = JSON.parse(body); } catch { res.writeHead(400, { 'Content-Type': 'text/plain' }); res.end('Invalid JSON'); return; } const task = { id: tasks.length + 1, title: data.title, done: false }; tasks.push(task); res.writeHead(201, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(task)); }); return; } res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('Not Found'); }); server.listen(3000);

The second uses Express:

const express = require('express'); const app = express(); app.use(express.json()); const tasks = [{ id: 1, title: 'Write the README', done: false }]; app.get('/tasks', (req, res) => { res.json(tasks); }); app.post('/tasks', (req, res) => { const task = { id: tasks.length + 1, title: req.body.title, done: false }; tasks.push(task); res.status(201).json(task); }); app.listen(3000);

Both servers return the same tasks. A POST /tasks request with the body {"title":"Buy milk"} gets the status 201 Created and the body {"id":2,"title":"Buy milk","done":false} from either one. The first program needs 40 lines for that work, and the second needs 18.

What Express Did for You

The difference in length comes from four jobs that the first program does by hand and the second program leaves to Express.

Choosing the code that runs. The raw server compares req.method and the path in a chain of if statements. Express lets you register one function for each combination of method and path, such as app.get('/tasks', ...), and calls the matching function. A path with its method and its function is called a route, and the function is the route's handler.

Reading the request body. A request body arrives in pieces, so the raw server collects the pieces with data and end events and then parses them. In Express, the single line app.use(express.json()) does that work, and the handler finds the parsed object in req.body.

Writing the response. The raw server sets the status code and the Content-Type header itself, and converts the object to a string. In Express, res.json(task) converts the object, sets Content-Type: application/json; charset=utf-8, and sends it. The call res.status(201) sets the status code first.

Answering requests that match nothing. The raw server ends with its own 404 response. Express sends a 404 response automatically when no route matches, as this request to the Express version shows:

GET /nothing HTTP/1.1 HTTP/1.1 404 Not Found Content-Type: text/html; charset=utf-8 <pre>Cannot GET /nothing</pre>

Express also rejects a body that is not valid JSON. When the body {"title": reaches express.json(), Express answers with 400 Bad Request before your handler runs. The response body is an HTML error page, and chapter 2 shows how to replace it with your own JSON error.

Express Runs on Top of the http Module

Express does not replace the Node.js http module. The object that express() returns is itself a function that takes a request and a response, (req, res), which is exactly the kind of function that http.createServer() accepts. When you call app.listen(3000), Express runs http.createServer(app) and starts that server on port 3000.

As a result, the req and res objects in an Express handler are the same Node.js request and response objects, with extra methods added. The method res.json() is an Express addition, while res.setHeader() and req.headers come from Node.js and still work.

Node.js accepts the connection and parses the HTTP request, and the Express app is the function that Node.js calls for every request.
Node.js accepts the connection and parses the HTTP request, and the Express app is the function that Node.js calls for every request.

In the diagram, notice that Node.js still does the network work and the parsing of the HTTP text. Express only decides which of your functions runs and gives those functions a shorter way to read the request and to write the response.

Why Developers Choose Express

Express is small. Its core contains routing, the request and response helpers, a few body parsers, and a static file server. Everything else, such as logging, authentication, or security headers, is added as a middleware package. A middleware is a function that runs for a request before the route's handler, and chapter 2 explains it in detail.

Express does not decide your structure. It does not require a folder layout, a pattern such as Model-View-Controller (MVC), or a particular database. You can use MVC, or any other structure, but you set it up yourself. Chapter 11 shows one way to structure a larger project.

Express does not include a database layer. Any Node.js database library works inside a handler, because a handler is an ordinary JavaScript function. Chapter 5 uses Mongoose for MongoDB and Sequelize for PostgreSQL.

Express has a large ecosystem. Many common needs already have a maintained middleware package. Examples used later in this course include morgan for request logs, helmet for security headers, cors for cross-origin requests, and multer for file uploads. Because Express has been the default choice for Node.js servers for many years, most Node.js tutorials, answers, and hosting guides assume it.

What It Costs

The freedom has a price. Because Express does not choose a project structure, a validation library, or an error format for you, every team makes those choices itself, and two Express projects can look very different.

Other Node.js frameworks make different trade-offs. Some build request validation against schemas into their design and focus on throughput. Others give every project a fixed structure of modules, controllers, and services, and some of these run on top of Express. Express is a good fit when you want a small core that you understand completely and that you extend one package at a time.

Which Version This Course Uses

Running npm install express today installs Express 5, and Express 5 requires Node.js 18 or later. This course teaches Express 5. Much of the Express code on the web was written for Express 4, and some of it no longer runs on Express 5. One example is a route path written as '*', which Express 5 rejects with an error when the app starts. The lessons point out each difference of this kind where it appears.

Reading Progress

0%


Vote for new content

On This Page

What Express Did for You

Express Runs on Top of the http Module

Why Developers Choose Express

What It Costs

Which Version This Course Uses