Express.js is among the most popular Node.js frameworks, and new versions are frequently published to upgrade or add new functionality. Some past releases have minimized the framework’s memory footprint, improved page load speeds, added new APIs and framework integrations, ensured code maintainability, and provided a better shorthand technique for calling and using functions.
The newly released Express.js v5 includes a slew of new features and enhancements aimed at improving the framework’s efficiency. However, this update may cause problems or generate deprecation warnings, making the migration a little unnerving.
In this tutorial, we’ll demonstrate how to upgrade from Express v4 to Express v5. We’ll also take a look at the upgrades and new features available in Express 5, and we’ll see how to build a web app in Express 5.
Let’s get going!
Jump ahead:
- Express.js overview
- Why migrate to Express 5?
- Express 4 vs. Express 5
- Migrating an Express 4 application to Express 5
- Express 5 app demo
Express.js overview
Express is a Node.js backend web application framework released under the MIT License as free and open source software. This popular Node web framework serves as the foundation for many other Node web frameworks, with a mechanism to:
- Create handlers for requests with various HTTP verbs and URL paths (routes)
- Integrate with “view” rendering engines to provide replies by populating templates with data
- Set up common web application settings such as the connection port and the location of templates for producing the answer
- Accommodate the addition of extra request processing middleware at each stage of the request handling pipeline
TJ Holowaychuk, the original author of Express, referred to it as a Sinatra-inspired server, a reference to its simplicity and to its numerous functionalities that are available as plugins.
Express, along with the MongoDB database software as well as a JavaScript frontend framework or library, is the backend component of makes up popular tech stacks such as MEAN, MERN, and MEVN.
Why migrate to Express.js v5?
Express 5 is still in beta, but as I mentioned earlier, it offers several updates over Express 4. These improvements are intended to increase the efficiency of the framework. The most significant changes relate to path route matching syntax. Let’s take a closer look.
Path route matching syntax
In Express 5, several changes have been made to the way a path string is matched to an incoming request:
- New parameter modifiers: ?, *, and +
- Named matching groups: no longer available by position in
req.params
- Regular expressions: may only be used in a matching group;
/(d+)
replaces/\\d+
- Matching group expressions: can only use RegExp syntax;
(.*)
replaces(*)
- Special
*
path segment behavior: this has been removed;/id/*/user
will match a literal*
as the middle segment
The string passed as the first input to the app.all()
, app.use()
, app.METHOD()
, router.all()
, router.METHOD()
, or router.use()
APIs is referred to as the path route matching syntax.
Rejected promises and middleware handlers
In Express 4, users rely on packages like express-async-handler
or write their helper functions to catch rejections of handlers that return promises.
However, in Express 5, any rejected promise or error thrown from middleware or handlers is forwarded as an error to the error handling middleware. This helps prevent the app from crashing.
This makes it easier to use async functions as middleware and handlers. When an async function throws an error or a rejected promise is awaited inside an async function, the error is sent to the error handler by calling the next (err)
function.
app.use(async (req, res, next) => { throw new Error("Something went wrong"); });
The above is equivalent to returning a Promise explicitly from a middleware or route handler in Express 4:
app.use((req, res, next) => { return new Promise((resolve, reject) => { reject(new Error("Something went wrong")); }); });
Return of the app.router
object
Express 5 has brought back the app.router
object, which was removed in Express 4. Unlike Express 3, in which an app was required to explicitly load the object, this object in Express 5 is essentially a reference to the underlying Express router.
Port maintained in req.host
object
Express 5 maintains the port number in the req.host
object. Previously, if a port number was provided, the req.host
method in Express 4 improperly removed the number.
req.query
object changed to getter
The req.query
property in Express 5 has been changed from a writable property to a getter. Additionally, the default query parser has been renamed “simple” from “extended”.
Express.js v4 vs. Express.js v5
Except for the updates mentioned previously, Express 5 is very similar to Express 4. The API hasn’t changed nearly as much as it did from v3 to v4. However, there are certain breaking changes, even though the underlying API has remained the same. In other words, updating an old Express 4 program to use Express 5 may cause it to fail.
Let’s take a closer look at the breaking changes:
app.del()
: this feature is no longer supported in Express 5, and an error will be thrown if you use this function- Solution: use the
app.delete()
function in place ofapp.del()
; delete is a reserved keyword in JavaScript, so del was initially used instead of delete; in ECMAScript 6, delete and other reserved keywords can now be properly used as property names - app.del(‘/user’, (req, res) => res.send(‘user deleted’));
// Will give deprecation warning in Express v4
// Will throw TypeError in Express v5
- Solution: use the
app.param(name, fn)
: this function has been depreciated since v4.11.0, and is not supported by Express 5; its functionality was changed using theapp.param(fn)
signaturereq.acceptsCharset()
,req.acceptsEncoding()
,req.acceptsLanguage()
have been pluralized is Express 5- Solution: use the following instead:
req.acceptsCharsets()
,req.acceptsEncodings()
, andreq.acceptsLanguages()
- Solution: use the following instead:
req.param(name)
: it’s not possible to retrieve form data with this function in Express 5- Solution: to retrieve form data, look for the submitted parameter name in the
req.params
,req.body
, orreq.query
object as shown in the following example:app.get(‘/user/:id’, (req, res) => { res.send(User.find(req.param(‘id’))); });
// Will give deprecation warning in Express v4
// Will throw TypeError in express v5 “req.param is not a function”// Do this instead in v5
app.get(‘/user/:id’, (req, res) => { res.send(User.find(req.params.id)); });
- Solution: to retrieve form data, look for the submitted parameter name in the
res.json
: this signature is not supported by Express 5. (obj, status).- Solution: use the
res.status(status).json(obj
syntax to change the status and then chain it to theres.json()
method, like so: - // Version 4
app.get(‘/user/:id’, (req, res) => { res.json(200, {user: User.find(req.param.id)}); });
// Version 5
app.get(‘/user/:id’, (req, res) => { res.status(200).json({ user: User.find(req.param.id) }); });
- Solution: use the
res.send(obj, status)
: this signature is not supported in Express 5- Solution: use
res.status(status).send()
to set the status and then chain it to theres.send()
method (obj), like so: - // Version 4
app.get(‘/user/:id’, (req, res) => {
res.send(200, {user: User.find(req.param.id)});
}); - // Version 5
app.get(‘/user/:id’, (req, res) => {
res.status(200).send({
user: User.find(req.params.id)
});
});
- Solution: use
res.send(status)
: this signature, wherestatus
is an integer, is not supported in Express 5- Solution: use the
res.sendStatus(statusCode)
function, which delivers the text version of the HTTP response header status code, such as “Not Found” or “Internal Server Error”; if you need to send a number using theres.send()
function, use quote marks to convert it to a string – otherwise, Express 5 may think you’re trying to use an unsupported old signature// Old method The res.send(status) // Version 5 res.sendStatus(statusCode)
- Solution: use the
Migrating an Express 4 application to Express 5
Migrating your Express 4 application to Express 5 is not as big of a lift as you may think.
To get started, move into the root directory of your project and install Express 5 using the following command:
npm install "express@>=5.0.0-beta.1" --save
This command will update your project dependencies and also update the package.json
file.
Next, rebuild the project or rerun your tests to determine if anything failed. Use the updates covered in this tutorial to fix any issues that may have occurred.
If you’d like to update any other npm packages in the project, run the npm outdated
command. This will enable you to see other packages in your project that need to be updated. Then, update them using the npm update
command.
Express.js v5 web app demo
To demonstrate what we’ve learned so far about Express 5, let’s create a demo todo application using the Express 5 syntax.
To get started, create a new folder for the application, like so:
mkdir express-5-demo && cd express-5-demo
Then, initialize a new Node.js project:
npm init -y
The above command will generate a package.json
file. Open the file and add a start script:
{ ... "start": "node index.js" }
Install dependencies
Now, install Express 5 and other required packages for this application with the following command:
npm i express@5.0.0-alpha.5 body-parser
Wait for the installation to finish before continuing. Once you’re certain that the installation is complete, create an index.js
file in the project’s root directory, and set up a basic Express server using the following code snippet:
const express = require("express"); const app = express(); app.listen(3000, ()=>console.log("Express server runing on port 3000"));
Create routes
With the Express server configured, let’s create some basic routes for the application. Update the index.js
file with the following code snippets:
const todos = [{ id: 1, title: "Learn Node.js", completed: true }, { id: 2, title: "Learn React.js", completed: false }, { id: 3, title: "Learn Angular.js", completed: false } ] app.get("/todos", (req, res) => { res.status(200).json(todos); }); app.post("/todos", (req, res) => { const todo = req.body; console.log(req.body); todos.push(todo); res.status(200).json(todos); }); app.get("/todos/:id", (req, res) => { const id = parseInt(req.params.id); const todo = todos.find(todo => todo.id === id); res.status(200).json(todo); }); app.put("/todos/:id", (req, res) => { const id = parseInt(req.params.id); const todo = todos.find(todo => todo.id === id); todo.completed = !todo.completed; res.status(200).json(todos); }); app.delete("/todos/:id", (req, res) => { const id = parseInt(req.params.id); const todo = todos.find(todo => todo.id === id); todos.splice(todos.indexOf(todo), 1); res.status(200).json(todos); });
In the above code, we created a todos
array with some dummy data. Then, we defined four API routes to get, add, update, and delete a todo
from the application.
Create middleware
To allow users to create a new todo
, we need to define a middleware for the body-parser package we just installed. Add the following code before the todos
array:
app.use(bodyPaerser.json());
Serve static files
We’ve completed the setup for our routes, so let’s create another router and middleware to serve up an HTML page to display the todos to the users.
First, create a new folder and name it public
. Then, create a new file called index.html
. Open the index.html
file and add the following code snippet:
<html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Todos</title> </head> <body> <div> <h3>Todos</h3> <ul id="data"></ul> </div> </body> </html> <style> #data{ list-style: none; padding: 0; } #data li{ display: inline-block; margin: 10px; padding: 10px; border: 1px solid #ccc; border-radius: 5px; } </style> <script src="app.js"></script>
In the above code, we created an HTML document to display the todos. The todos will be displayed in the <ul id="data"></ul>
section of the page, which we’ll handle with JavaScript. We also defined some styling and referenced the JavaScript file which we’ll create shortly to get all the todos.
Now create an app..js
file in the public folder and add the following code:
const Tododata = document.getElementById('data'); fetch('http://localhost:3001/todos', { method: 'GET', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' } }) .then(res => res.json()) .then(data => { if(data){ data.forEach(element => { const li = document.createElement('li'); li.innerHTML = element.title; Tododata.appendChild(li); }); } }) .catch(err => console.log(err));
Here we send a request to the backend, using the JavaScript fetch
API, to check if a todo
exists in the todos
array. Then we create a list element to display the details of the todos.
For the page to render, we need to add one more configuration to the root index.js
file. Add the code below after const app = express();
app.use(express.static(__dirname + "/public"));
Now we’ll be able to render all the static files in the public
directory.
Test the application
To test the application, run the following command to start the Express server:
npm start
Then, navigate in your browser to localhost:3000
, and you should see the following output:
Conclusion
In this article, we explored the new features and improvements available in Express.js v5 and reviewed how to migrate an existing Express 4 app to Express 5. To demonstrate how to take advantage of the new functionalities available in version 5, we created a step-by-step demo showing how to create a web app in Express 5.
What are your thoughts on Express 4 vs. Express 5? Do you plan to migrate to Express 5 in your next project? For additional information about Express 5, check out the official documentation.
The post Express.js 5 migration guide appeared first on LogRocket Blog.
from LogRocket Blog https://ift.tt/dLbEQeX
via Read more