Express is a server-side web application framework built on top of Node.js. It is minimal, flexible, and provides a robust set of features and clean APIs. Today, Express is extremely popular because of its simplicity, ease-of-use and extensibility.

Express has an entire ecosystem of packages that allow you to easily do whatever you want which makes getting started with it a breeze.

In this tutorial, we will learn how to use Express, including installing, building a hello world example, sending and receiving data, use routing, add middleware, utilize template engines, and more.

Prerequisites

  1. Node and NPM installed. If you don't have them installed, follow our how to install Node guide.

Installing Yarn

We will be using Yarn to manage our dependencies. This step is technically optional because you can just stick to npm if you prefer. To install Yarn, run this:

BASH
npm install -g yarn

To test if you've installed Yarn, check the version:

BASH
yarn -v

If you see a version number, you're good to go.

Installing Express

Installing Express is very simple. We can install it using Yarn.

BASH
yarn add express

Alternatively, you can use NPM.

BASH
npm install express

If you need to set up a project from scratch, initialize one using npm:

BASH
npm init

This will create a package.json file for you.

Creating a simple Express app

Now that we have Express installed, we can create a simple Express app. Create a file called index.js and add this:

JAVASCRIPT
import express from "express"; const app = express(); const port = 3000; app.get("/", (req, res) => { res.send("Hello World from Sabe.io!"); }); app.listen(port, () => { console.log(`App listening at http://localhost:${port}`); });

Now, let's run this app. To do this, run the following command:

BASH
node index.js

You should see the following output:

BASH
App listening at http://localhost:3000

Now, navigate to http://localhost:3000 in your browser. You should see the following:

The hello world example.

Express basics

Now that we have our app running, we can start to get into the details of what is going on.

JAVASCRIPT
import express from "express";

This creates an instance of the Express application using the express module.

JAVASCRIPT
const app = express();

Next, we instantiate an Express application by calling the express method and store it in a variable called app.

JAVASCRIPT
const port = 3000;

This is the port we will be using to run our app. We use 3000 because this is the default port for Express.

JAVASCRIPT
app.get("/", (req, res) => { res.send("Hello World from Sabe.io!"); });

This creates a route for our app. The first argument is the path we want to use. The second argument is the router handler, a callback function that will be called when a request is made to the path. The callback function takes two arguments: req is the request object and res is the response object. The response object is used to send data back to the client. In this case, we are sending a string back to the client that says Hello World from Sabe.io!.

While this uses the GET method, you can also use POST, PUT, DELETE, and PATCH methods. Here's how to use each one:

JAVASCRIPT
app.get("/", (req, res) => { // GET }); app.post("/", (req, res) => { // POST }); app.put("/", (req, res) => { // PUT }); app.delete("/", (req, res) => { // DELETE }); app.patch("/", (req, res) => { // PATCH });

When Express receives a request to the path /, it will call the callback function. In our case, when the user visits http://localhost:3000/, the path matches / and was a GET request. Because of this, Express executed the callback function which sent the response back to the client and then closes the connection.

JAVASCRIPT
app.listen(port, () => { console.log(`App listening at http://localhost:${port}`); });

This creates a listener for the app. The first argument is the port we want to listen on. The second argument is a callback function that will be called when the server is ready to accept connections. The callback function will print a message to the console to let us know that the server is ready, in this case, that it is listening on port 3000.

Routing

We've seen how to route a request to / and send a response back to the client, however Express has support for more complex routing, like named parameters. Named parameters are routers that accept a variable as part of the path. For example, if we wanted to route a request to /users/:id, we would use the following:

JAVASCRIPT
app.get("/users/:id", (req, res) => { res.send(`User ${req.params.id}`); });

Now if you visit http://localhost:3000/users/1, you should see the following output:

BASH
User 1

This is because the :id is a named parameter. The :id is a placeholder for the value of the parameter. In this case, the value of the parameter is 1. All of the named parameters are stored in the req.params object which you can access from the callback function.

Named parameters is not the only complex routing you can use. You can also use regular expressions. Regular expressions are used to match a string against a pattern. For example, if we wanted to only match our /users/ route if the :id is a number, we could use the following:

JAVASCRIPT
app.get("/users/:id(\\d+)", (req, res) => { res.send(`User ${req.params.id}`); });

If you visit http://localhost:3000/users/23, you should see the following output:

BASH
User 23

But if you tried to visit http://localhost:3000/users/23hello, you would see the following output:

BASH
Cannot GET /users/23hello

This is because 23hello does not match the regular expression, which requires the :id to be a number. Because no route matched, Express returned a 404 error.

Responses

Express supports many different ways to send data back to the client. The most common way is to use the res.send() method, which we did in the previous section. This method takes a string as an argument and sends it back to the client. When you send a string, Express sets the content type to text/html automatically. Sometimes, you don't always want this, as in cases where you aren't sending plain text or HTML back to the client.

If you send an array or Object, Express will automatically set the content type to application/json. You can also set the content type manually using the res.type() method. Here's how to do this:

JAVASCRIPT
app.get("/", (req, res) => { res.type("json"); res.send(`{"response":"Hello World from Sabe.io!"}`); });

Another way to send a JSON response is to use the res.json() method. This method takes an object as an argument and sends it back to the client.

JAVASCRIPT
app.get("/", (req, res) => { res.json({"response":"Hello World from Sabe.io!"}); });

The res.json() method is a shortcut for res.type("json") and res.send(). It is a common pattern to use this method when you want to send a JSON response because it will stringify the object and set the content type to application/json automatically for you.

You can also manually set any header you want using the res.set() method. Here's how to do this:

JAVASCRIPT
res.set("Content-Type", "application/json");

HTTP Response Status Codes

Express gives you control over the HTTP response status code. You can set the status code using the res.status() method. Here's how to do this:

JAVASCRIPT
app.get("/", (req, res) => { res.status(404); res.send("Not Found"); });

This sets the response status code to 404 and lets the client know that the page they are looking for doesn't exist.

By default, Express uses the 200 status code, however, you can set the status code to anything you want.

Here are the most common status codes:

JAVASCRIPT
app.get("/", (req, res) => { res.status(200); res.send("OK"); });
JAVASCRIPT
app.get("/", (req, res) => { res.status(301); res.send("Moved permanently"); });
JAVASCRIPT
app.get("/", (req, res) => { res.status(302); res.send("Found"); });
JAVASCRIPT
app.get("/", (req, res) => { res.status(401); res.send("Unauthorized"); });
JAVASCRIPT
app.get("/", (req, res) => { res.status(403); res.send("Forbidden"); });
JAVASCRIPT
app.get("/", (req, res) => { res.status(404); res.send("Not Found"); });
JAVASCRIPT
app.get("/", (req, res) => { res.status(500); res.send("Internal Server Error"); });

Redirects

Redirects are a common way to handle client-side routing. When you want to redirect the user to another page, you can use the res.redirect() method. Here's how to do this:

JAVASCRIPT
app.get("/", (req, res) => { res.redirect("/about"); });

This will redirect the user to the /about page when they visit http://localhost:3000/. This will send a 302 status code to the client which means the page was temporarily moved to another location. Sometimes you want to declare that this move was permanent. In this case, you can use the res.redirect() method with the 301 status code.

JAVASCRIPT
app.get("/", (req, res) => { res.redirect(301, "/about"); });

This will send a 301 status code to the client and redirect the user to the /about page.

In addition to relative paths, you can also redirect to an absolute URL. Here's how to do this:

JAVASCRIPT
app.get("/", (req, res) => { res.redirect("http://sabe.io"); });

You can also redirect to a level back in the URL structure using the .. syntax. Here's how to do this:

JAVASCRIPT
app.get("/", (req, res) => { res.redirect("../about"); });

This will redirect the user to the /about page after going one level back in the URL structure.

Finally, you can redirect back a page like this:

JAVASCRIPT
app.get("/", (req, res) => { res.redirect("back"); });

This is equivalent to using the req.header("Referer") method to get the previous page.

Cookies

Express has robust support for cookies. Cookies are used to store information about the user. For example, if you want to store the user's name, you can do this:

JAVASCRIPT
app.get("/", (req, res) => { res.cookie("name", "Sabe"); res.send("Hello World from Sabe.io!"); });

This example adds a cookie to the response. The first argument is the name of the cookie. The second argument is the value of the cookie. The third argument is an object that contains options for the cookie. The options are:

  • maxAge: The number of milliseconds the cookie should be valid for.
  • signed: Whether or not the cookie should be signed.
  • httpOnly: Whether or not the cookie should be accessible by JavaScript.
  • secure: Whether or not the cookie should be sent over HTTPS.
  • path: The path that the cookie should be valid for, the default is /.
  • domain: The domain that the cookie should be valid for, the default is undefined.
  • expires: The date that the cookie should expire, the default is undefined.

These options give you powerful control over the cookies that are sent to the client.

When you're read to remove the cookie, you can do so by using the res.clearCookie() method. Here's how to do this:

JAVASCRIPT
app.get("/clear", (req, res) => { res.clearCookie("name"); });

Downloads

Express makes serving downloads very easy. The browser can do one of those things when presented with a resources, display it or download it. By default, the browser will choose to display it (like an image or PDF file). However, you can use the res.download() method to request that the browser to download the file instead. Here's how to do this:

JAVASCRIPT
app.get("/download", (req, res) => { res.download("/path/to/file"); });

You can even control the filename that the browser will use when downloading the file. You can do this by passing a second argument to the res.download() method. Here's how that looks:

JAVASCRIPT
app.get("/download", (req, res) => { res.download("/path/to/file", "filename.png"); });

Now when the user downloads the file, the browser will use filename.png as the file name instead of the original file's name.

Middleware

Middleware, as the name suggests, is functions that are run in between the handling of requests. They have access to the request and response object, meaning they are very powerful and can do a lot. They can change the request or response object, add new headers, redirect the user to another page, end the response cycle, and much more.

Because of this Middleware is a great way to add functionality to your application. You can easily create your own or use existing middleware packages.

Middleware for Express takes three parameters, req, res, and next. The next parameter is a function that you can call to pass control to the next middleware in the chain. You can use this function to stop the request from continuing to the next middleware or to end the response cycle. But in most cases, you will want to use the next() function so that the request can continue onwards.

Here's a basic example of a middleware function that logs the request to the console:

JAVASCRIPT
app.use((req, res, next) => { console.log("Request: ", req.url); next(); });

Now if you visit http://localhost:3000/log you will see the request logged to the console.

BASH
Request: /log

After it logs the request, the request will continue on to the next middleware in the chain.

Keep in mind that you can make middleware only run on specific routes. For example, you can make a middleware only run on the /log route:

JAVASCRIPT
app.use("/log", (req, res, next) => { console.log("Request: ", req.url); next(); });

Now this middleware will only run on the /log route.

Middleware can even be used to handle errors. Here's an example of a middleware that handles errors:

JAVASCRIPT
app.get("/", (req, res) => { const err = new Error("Error occurred!"); next(err); }); app.use((error, req, res, next) => { console.log("Error!"); console.log(error); next(); });

Your console should look like this after visiting http://localhost:3000/.

BASH
node index.js App listening at http://localhost:3000 Error! Error: Error occurred!

Express comes with a number of middleware packages that you can use but as mentioned before, you can install third-party middleware. This makes Express flexible and powerful, with little work needed on the user to add complex functionality very quickly.

Templates

Server-side templates are an important part of Express. They are used to render dynamic HTML pages in your application. Templates, also called views, are blueprints for your HTML, where you can pass in data and render them.

To do so, simply use the res.render() method. Here's how to do this:

JAVASCRIPT
app.get("/", (req, res) => { res.render("index", { title: "My Page", message: "Hello World!" }); });

res.render() takes two arguments:

  • view: The name of the template to render.
  • options: An object containing the data to pass to the template.

In this example, we are rendering the index template with the title and message properties. This makes it dynamic because I can re-use the same template for different pages and just change the data being passed in to the template.

The default template engine is Jade, however you can use any template engine that you want. Here's how to use the EJS template engine:

First, install ejs:

BASH
npm install ejs

or using yarn:

BASH
yarn add ejs

Then set the template engine to EJS:

JAVASCRIPT
app.set("view engine", "ejs");

Create a new file called index.ejs in the views directory.

HTML
<html> <head> <title><%- title %></title> </head> <body> <h1><%- message %></h1> </body> </html>

If all goes well, you should see the following in your browser:

EJS with Express

Here's the entire code for using the EJS template engine with Express:

JAVASCRIPT
import express from "express"; const app = express(); const port = 3000; app.set("view engine", "ejs"); app.get("/", (req, res) => { res.render("index", { title: "My Page", message: "Hello World!" }); }); app.listen(port, () => { console.log(`App listening at http://localhost:${port}`); });

Serving Static Files

Express can serve static files such as images, CSS, and JavaScript files, basically any resource that doesn't change between requests. Static files are usually served out of a folder called public, because the files in there are meant to be accessible to all. You can alternatively serve static files from a folder called static or any folder you want.

To serve static resources from a folder, use the static middleware for it. It will handle all requests to the folder you specify. Here's an example of serving static files from the public folder:

JAVASCRIPT
app.use(express.static("public"));

As long as you have a folder with that name in the root, you can access the files in that folder by using the URL http://localhost:3000/public/filename.

Conclusion

Express is a powerful framework that can be used to build web applications. With its support for middleware, you can add powerful functionality to your application quickly and easily. Express has everything you need to build a robust web application leveraging the full power of Node and JavaScript.

If you want to learn how to deploy your Express application using Docker, check out our How to deploy an Express app using Docker tutorial.

Happy coding and thanks for reading!

Resources

Recommended Tutorial »
Copyright © 2017 - 2024 Sabe.io. All rights reserved. Made with ❤ in NY.