Node.js is a quick JavaScript runtime environment used for creating server-side apps. Express.js is needed to handle file serving, request handling, and HTTP method handling. According to its documentation, Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.
In this tutorial, we'll explore the newly released Express.js V5 and how to upgrade from Express.js V4 to V5. We'll also look at the enhancements and new features provided by Express.js V5, as well as explore how it can be used to build a web application.
The recently released Express.js V5 contains a number of enhancements and new features aimed at boosting the functionality of the framework. The migration from V4 to V5 might be a little disconcerting, though, because of possible problems or deprecation of features within this update.
Overview of Express.js
Express.js as a Node.js backend framework is efficient for building restful server-side applications. Express.js apps process client requests using particular HTTP request methods and route paths. They also carry out route handler callbacks that have been set up for the routes.
Express has a well-structured approach to middleware functions that can easily be incorporated into the request-response processing cycles. The structure gives each middleware function the needed access to other middleware functions, forming a chain of addition processing on the incoming request and the outgoing response. This provides the developers with easy access and termination of request-response cycles within the middleware functions.
Why Migrate from Express.js V4 to V5?
At the core of the new features and improvements in Express.js V5 is the increased efficiency of the framework. This improves the general performance of the server-side applications built with it. Amongst the improvements is the handling of rejected promises. Previously, we explicitly implemented error handlers for rejected promises or errors. Now, we can simply send the errors to an error handling middleware to properly process them as well.
Let's explore the changes even further, but please note that Express.js V5 is still in its beta stage.
Rejected Promise and Error Handling
In Express.js V4, when an error or rejection in a request handler is not explicitly handled or passed down to an error-handling middleware, it could potentially cause the app to crash. However, with Express.js V5, the application doesnât crash; instead, a 500 response containing either the error or the rejected value is returned. Better yet, we can handle the event by passing it down to an error-handling middleware.
app.get("/throw", async () => {
return await Promise.resolve().then(() => {
throw new Error("Pieces: error");
});
});
app.get("/reject", () => {
return Promise.reject("Pieces: rejected");
});
The above snippet would surely crash the entire application in Express.js V4, but thanks to V5 updates, it wonât.
Return of app.router Object
The app.router reference object to an Express appâs built-in router instance, which was removed in Express.js V4, has been brought back in V5. Now, we can define middleware and routes on the app.router
object:
const express = require("express");
const app = express();
const router = app.router;
router.post("/create", (req, res) => {
// do something...
res.status(status).send("Created from Pieces!");
});
Change of Syntax for Route Path Matching
Express.js V5 came with new parameter modifiers to the route path. Route paths, which define endpoints as strings, string patterns, or regular expressions, are mostly utilized in app and router objects for incoming requests. These changes include:
- The use of the
?
,*
, and+
characters, which should be added as suffixes to route parameters. - The use of
?
to specify optional parameters. - The use of
*
to match zero or more parameters. - The use of
+
for one or more parameters. - When using regular expressions in matching groups:
-
/(\\d+)
replaced/\\d+
-
(*)
wonât be valid any longer, and must be written as(.*)
. - The use of
req.params
in a named matching group like/:foo(.*)
can only be captured asreq.params.foo
, and is not available asreq.params[0]
.
app.get("/inventory/:ids*/pieces", (req, res) => {
res.status(status).send("Check the warehouse inventory!");
});
The above snippet shows a route path that will match /inventory/pieces
, /inventory/1/pieces
, /inventory/1/2/pieces
, and so on when substituted.
app.get("/inventory/:ids+/pieces", (req, res) => {
res.status(status).send("Get the warehouse inventory with id!");
});
The above snippet shows a route path that will match /inventory/1/pieces
, /inventory/1/2/pieces
, and so on when substituted, but not /inventory/pieces
.
app.get("/inventory/:id?/pieces", (req, res) => {
res.status(status).send("Check only the warehouse inventory!");
});
The above snippet shows a route path that will match /inventory/pieces
, /inventory/1/pieces
, and so on when substituted, but not /inventory/1/2/pieces
.
As mentioned above, all matching group expressions have to be RegExp. In Express.js V4, the use of (*)
in route path was valid, but will fail in Express.js V5. The valid RegExp equivalent is (.*)
.
app.get("/inventory/:id(.*)", (req, res) => {
res.status(status).send(req.params);
});
The above snippet will return {"id":"1"}
as a response in Express.js V5, unlike (*)
, which will return {"0":"1","id":"1"}
as a response in Express.js V4.
Asynchronous Behavior by res.render
The res.render
in Express.js V5 now supports asynchronous callback as its parameter. This improvement helps avoid bugs caused by view engines that are synchronous in implementation; the callback function handles any rendering error that may occur when trying to send the rendered HTML as a response to the client.
Changes to the req.query Object
The nature of the req.query
property has been changed to a getter
, unlike its writable nature in Express.js V4. The default query parser has been changed from extended to simple. This update also comes with the equivalent setter to change the default query parser if need be.
const express = require("express");
const app = express();
console.log(app.get("query parser"));
app.set("query parser", "extended");
The Use of req.host to Manage Port
The req.host
property now manages and returns the host value from the Host HTTP header. For example, if the server-side application is running on http://localhost:8080
, then the code below will return localhost:3000
on Express.js V5:
app.get("/heath-check", (req, res) => {
res.status(status).send(`host: ${req.host}`);
});
Additional Breaking Changes in Express.js V5 from V4
Letâs enumerate some potential breaking changes introduced in V5:
- The
req.acceptsCharset()
,req.acceptsEncoding()
, andreq.acceptsLanguage()
functions have been pluralized toreq.acceptsCharsets()
,req.acceptsEncodings()
, andreq.acceptsLanguages()
in Express.js V5. - The
app.del()
function for registeringHTTP DELETE
routes has been renamed toapp.delete()
.
The following function signatures have been changed as shown below:
-
res.json(obj, status
) tores.status(status).json(obj)
-
res.send(body, status)
tores.status(status).send(obj)
-
res.jsonp(obj, status)
tores.status(status).jsonp(obj)
-
res.send(status)
(wherestatus
is a number) tores.sendStatus(statusCode)
-
res.sendfile()
tores.sendFile()
- The deprecated function signature,
app.param(fn)
, is no longer supported in Express.js V5
Migrating an Existing Express.js V4 Application to V5
Luckily, migrating an existing server-side application to Express.js V5 wonât involve a lot of heavy lifting. The first approach would be to upgrade from V4 to V5 of Express.js by running the command below:
npm install "express@>=5.0.0-beta.1" --save
First, run the npm outdated command to see any packages that need to be updated. Next, re-run any existing test suites on the project, or rebuild the entire project to see all breaking changes. Follow the tutorial to fix any issues that occur.
Conclusion
In this article, we explored the exciting new features and improvements in Express.js V5, including the addition of route parameter modifier characters, and improved RegExp
parsing in route paths. Express.js V5 has restored critical attributes and values that were absent from Express.js V4, such as app.router
and the port in req.host
. Furthermore, synchronous view rendering bugs have been resolved. Likewise, V5 handles rejected promise handling in middleware and handlers automatically. For more information about Express.js V5, check out the documentation.