Express is an extremely commonly used web server application framework in Node.js. Essentially, a framework is a code structure that adheres to specific rules and has two key characteristics:
- It encapsulates APIs, enabling developers to concentrate more on writing business code.
- It has established processes and standard specifications.
The core features of the Express framework are as follows:
- It can configure middleware to respond to various HTTP requests.
- It defines a route table for executing different types of HTTP request actions.
- It supports passing parameters to templates to achieve dynamic rendering of HTML pages.
This article will analyze how Express implements middleware registration, the next mechanism, and route handling by implementing a simple LikeExpress class.
Express Analysis
Let's first explore the functions it provides through two Express code examples:
Express Official Website Hello World Example
const express = require('express'); const app = express(); const port = 3000; app.get('/', (req, res) => { res.send('Hello World!'); }); app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`); });
Analysis of the Entry File app.js
The following is the code of the entry file app.js of the Express project generated by the express-generator scaffolding:
// Handle errors caused by unmatched routes const createError = require('http-errors'); const express = require('express'); const path = require('path'); const indexRouter = require('./routes/index'); const usersRouter = require('./routes/users'); // `app` is an Express instance const app = express(); // View engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); // Parse JSON format data in post requests and add the `body` field to the `req` object app.use(express.json()); // Parse the urlencoded format data in post requests and add the `body` field to the `req` object app.use(express.urlencoded({ extended: false })); // Static file handling app.use(express.static(path.join(__dirname, 'public'))); // Register top-level routes app.use('/', indexRouter); app.use('/users', usersRouter); // Catch 404 errors and forward them to the error handler app.use((req, res, next) => { next(createError(404)); }); // Error handling app.use((err, req, res, next) => { // Set local variables to display error messages in the development environment res.locals.message = err.message; // Decide whether to display the full error according to the environment variable. Display in development, hide in production. res.locals.error = req.app.get('env') === 'development'? err : {}; // Render the error page res.status(err.status || 500); res.render('error'); }); module.exports = app;
From the above two code segments, we can see that the Express instance app mainly has three core methods:
-
app.use([path,] callback [, callback...]): Used to register middleware. When the request path matches the set rules, the corresponding middleware function will be executed.
- path: Specifies the path for invoking the middleware function.
- callback: The callback function can take various forms. It can be a single middleware function, a series of middleware functions separated by commas, an array of middleware functions, or a combination of all the above.
- app.get() and app.post(): These methods are similar to use(), also for registering middleware. However, they are bound to HTTP request methods. Only when the corresponding HTTP request method is used will the registration of the relevant middleware be triggered.
- app.listen(): Responsible for creating an httpServer and passing the parameters required by server.listen().
Code Implementation
Based on the analysis of the functions of the Express code, we know that the implementation of Express focuses on three points:
- The registration process of middleware functions.
- The core next mechanism in the middleware functions.
- Route handling, with a focus on path matching.
Based on these points, we will implement a simple LikeExpress class below.
1. Basic Structure of the Class
First, clarify the main methods that this class needs to implement:
- use(): Implements general middleware registration.
- get() and post(): Implement middleware registration related to HTTP requests.
- listen(): Essentially, it is the listen() function of httpServer. In the listen() function of this class, an httpServer is created, parameters are passed through, requests are listened to, and the callback function (req, res) => {} is executed.
Review the usage of the native Node httpServer:
const express = require('express'); const app = express(); const port = 3000; app.get('/', (req, res) => { res.send('Hello World!'); }); app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`); });
Accordingly, the basic structure of the LikeExpress class is as follows:
// Handle errors caused by unmatched routes const createError = require('http-errors'); const express = require('express'); const path = require('path'); const indexRouter = require('./routes/index'); const usersRouter = require('./routes/users'); // `app` is an Express instance const app = express(); // View engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); // Parse JSON format data in post requests and add the `body` field to the `req` object app.use(express.json()); // Parse the urlencoded format data in post requests and add the `body` field to the `req` object app.use(express.urlencoded({ extended: false })); // Static file handling app.use(express.static(path.join(__dirname, 'public'))); // Register top-level routes app.use('/', indexRouter); app.use('/users', usersRouter); // Catch 404 errors and forward them to the error handler app.use((req, res, next) => { next(createError(404)); }); // Error handling app.use((err, req, res, next) => { // Set local variables to display error messages in the development environment res.locals.message = err.message; // Decide whether to display the full error according to the environment variable. Display in development, hide in production. res.locals.error = req.app.get('env') === 'development'? err : {}; // Render the error page res.status(err.status || 500); res.render('error'); }); module.exports = app;
2. Middleware Registration
From app.use([path,] callback [, callback...]), we can see that middleware can be an array of functions or a single function. To simplify the implementation, we uniformly process the middleware as an array of functions. In the LikeExpress class, the three methods use(), get(), and post() can all implement middleware registration. Only the triggered middleware varies due to different request methods. So we consider:
- Abstracting a general middleware registration function.
- Creating arrays of middleware functions for these three methods to store the middleware corresponding to different requests. Since use() is a general middleware registration method for all requests, the array storing use() middleware is the union of the arrays for get() and post().
Middleware Queue Array
The middleware array needs to be placed in a public area for easy access by methods in the class. So, we put the middleware array in the constructor() constructor function.
const http = require("http"); const server = http.createServer((req, res) => { res.end("hello"); }); server.listen(3003, "127.0.0.1", () => { console.log("node service started successfully"); });
Middleware Registration Function
Middleware registration means storing the middleware in the corresponding middleware array. The middleware registration function needs to parse the incoming parameters. The first parameter may be a route or middleware, so it is necessary to first determine whether it is a route. If it is, output it as it is; otherwise, the default is the root route, and then convert the remaining middleware parameters into an array.
const http = require('http'); class LikeExpress { constructor() {} use() {} get() {} post() {} // httpServer callback function callback() { return (req, res) => { res.json = function (data) { res.setHeader('content-type', 'application/json'); res.end(JSON.stringify(data)); }; }; } listen(...args) { const server = http.createServer(this.callback()); server.listen(...args); } } module.exports = () => { return new LikeExpress(); };
Implementation of use(), get(), and post()
With the general middleware registration function register(), it is easy to implement use(), get(), and post(), just store the middleware in the corresponding arrays.
const express = require('express'); const app = express(); const port = 3000; app.get('/', (req, res) => { res.send('Hello World!'); }); app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`); });
3. Route Matching Processing
When the first parameter of the registration function is a route, the corresponding middleware function will be triggered only when the request path matches the route or is its sub-route. So, we need a route matching function to extract the middleware array of the matching route according to the request method and request path for the subsequent callback() function to execute:
// Handle errors caused by unmatched routes const createError = require('http-errors'); const express = require('express'); const path = require('path'); const indexRouter = require('./routes/index'); const usersRouter = require('./routes/users'); // `app` is an Express instance const app = express(); // View engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); // Parse JSON format data in post requests and add the `body` field to the `req` object app.use(express.json()); // Parse the urlencoded format data in post requests and add the `body` field to the `req` object app.use(express.urlencoded({ extended: false })); // Static file handling app.use(express.static(path.join(__dirname, 'public'))); // Register top-level routes app.use('/', indexRouter); app.use('/users', usersRouter); // Catch 404 errors and forward them to the error handler app.use((req, res, next) => { next(createError(404)); }); // Error handling app.use((err, req, res, next) => { // Set local variables to display error messages in the development environment res.locals.message = err.message; // Decide whether to display the full error according to the environment variable. Display in development, hide in production. res.locals.error = req.app.get('env') === 'development'? err : {}; // Render the error page res.status(err.status || 500); res.render('error'); }); module.exports = app;
Then, in the callback function callback() of the httpServer, extract the middleware that needs to be executed:
const http = require("http"); const server = http.createServer((req, res) => { res.end("hello"); }); server.listen(3003, "127.0.0.1", () => { console.log("node service started successfully"); });
4. Implementation of the next Mechanism
The parameters of the Express middleware function are req, res, and next, where next is a function. Only by calling it can the middleware functions be executed in sequence, similar to next() in ES6 Generator. In our implementation, we need to write a next() function with the following requirements:
- Extract one middleware from the middleware queue array in order each time.
- Pass the next() function into the extracted middleware. Because the middleware array is public, each time next() is executed, the first middleware function in the array will be taken out and executed, thus achieving the effect of sequential execution of middleware.
const http = require('http'); class LikeExpress { constructor() {} use() {} get() {} post() {} // httpServer callback function callback() { return (req, res) => { res.json = function (data) { res.setHeader('content-type', 'application/json'); res.end(JSON.stringify(data)); }; }; } listen(...args) { const server = http.createServer(this.callback()); server.listen(...args); } } module.exports = () => { return new LikeExpress(); };
Express Code
constructor() { // List of stored middleware this.routes = { all: [], // General middleware get: [], // Middleware for get requests post: [], // Middleware for post requests }; }
Leapcell: The Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis
Finally, let me introduce a platform that is very suitable for deploying Express: Leapcell.
Leapcell is a serverless platform with the following characteristics:
1. Multi-Language Support
- Develop with JavaScript, Python, Go, or Rust.
2. Deploy unlimited projects for free
- Pay only for usage — no requests, no charges.
3. Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
4. Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
5. Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the documentation!
Leapcell Twitter: https://x.com/LeapcellHQ
The above is the detailed content of Mastering Express.js: A Deep Dive. For more information, please follow other related articles on the PHP Chinese website!

Introduction I know you may find it strange, what exactly does JavaScript, C and browser have to do? They seem to be unrelated, but in fact, they play a very important role in modern web development. Today we will discuss the close connection between these three. Through this article, you will learn how JavaScript runs in the browser, the role of C in the browser engine, and how they work together to drive rendering and interaction of web pages. We all know the relationship between JavaScript and browser. JavaScript is the core language of front-end development. It runs directly in the browser, making web pages vivid and interesting. Have you ever wondered why JavaScr

Node.js excels at efficient I/O, largely thanks to streams. Streams process data incrementally, avoiding memory overload—ideal for large files, network tasks, and real-time applications. Combining streams with TypeScript's type safety creates a powe

The differences in performance and efficiency between Python and JavaScript are mainly reflected in: 1) As an interpreted language, Python runs slowly but has high development efficiency and is suitable for rapid prototype development; 2) JavaScript is limited to single thread in the browser, but multi-threading and asynchronous I/O can be used to improve performance in Node.js, and both have advantages in actual projects.

JavaScript originated in 1995 and was created by Brandon Ike, and realized the language into C. 1.C language provides high performance and system-level programming capabilities for JavaScript. 2. JavaScript's memory management and performance optimization rely on C language. 3. The cross-platform feature of C language helps JavaScript run efficiently on different operating systems.

JavaScript runs in browsers and Node.js environments and relies on the JavaScript engine to parse and execute code. 1) Generate abstract syntax tree (AST) in the parsing stage; 2) convert AST into bytecode or machine code in the compilation stage; 3) execute the compiled code in the execution stage.

The future trends of Python and JavaScript include: 1. Python will consolidate its position in the fields of scientific computing and AI, 2. JavaScript will promote the development of web technology, 3. Cross-platform development will become a hot topic, and 4. Performance optimization will be the focus. Both will continue to expand application scenarios in their respective fields and make more breakthroughs in performance.

Both Python and JavaScript's choices in development environments are important. 1) Python's development environment includes PyCharm, JupyterNotebook and Anaconda, which are suitable for data science and rapid prototyping. 2) The development environment of JavaScript includes Node.js, VSCode and Webpack, which are suitable for front-end and back-end development. Choosing the right tools according to project needs can improve development efficiency and project success rate.

Yes, the engine core of JavaScript is written in C. 1) The C language provides efficient performance and underlying control, which is suitable for the development of JavaScript engine. 2) Taking the V8 engine as an example, its core is written in C, combining the efficiency and object-oriented characteristics of C. 3) The working principle of the JavaScript engine includes parsing, compiling and execution, and the C language plays a key role in these processes.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

Atom editor mac version download
The most popular open source editor

Dreamweaver CS6
Visual web development tools

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.
