Getting Started with Express
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
- 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:
BASHnpm install -g yarn
To test if you've installed Yarn, check the version:
BASHyarn -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.
BASHyarn add express
Alternatively, you can use NPM.
BASHnpm install express
If you need to set up a project from scratch, initialize one using npm:
BASHnpm 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:
JAVASCRIPTimport 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:
BASHnode index.js
You should see the following output:
BASHApp 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.
JAVASCRIPTimport express from "express";
This creates an instance of the Express application using the express
module.
JAVASCRIPTconst app = express();
Next, we instantiate an Express application by calling the express
method and store it in a variable called app
.
JAVASCRIPTconst 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.
JAVASCRIPTapp.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:
JAVASCRIPTapp.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.
JAVASCRIPTapp.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:
JAVASCRIPTapp.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:
BASHUser 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:
JAVASCRIPTapp.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:
BASHUser 23
But if you tried to visit http://localhost:3000/users/23hello
, you would see the following output:
BASHCannot 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:
JAVASCRIPTapp.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.
JAVASCRIPTapp.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:
JAVASCRIPTres.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:
JAVASCRIPTapp.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:
JAVASCRIPTapp.get("/", (req, res) => {
res.status(200);
res.send("OK");
});
JAVASCRIPTapp.get("/", (req, res) => {
res.status(301);
res.send("Moved permanently");
});
JAVASCRIPTapp.get("/", (req, res) => {
res.status(302);
res.send("Found");
});
JAVASCRIPTapp.get("/", (req, res) => {
res.status(401);
res.send("Unauthorized");
});
JAVASCRIPTapp.get("/", (req, res) => {
res.status(403);
res.send("Forbidden");
});
JAVASCRIPTapp.get("/", (req, res) => {
res.status(404);
res.send("Not Found");
});
JAVASCRIPTapp.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:
JAVASCRIPTapp.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.
JAVASCRIPTapp.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:
JAVASCRIPTapp.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:
JAVASCRIPTapp.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:
JAVASCRIPTapp.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:
JAVASCRIPTapp.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 isundefined
.expires
: The date that the cookie should expire, the default isundefined
.
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:
JAVASCRIPTapp.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:
JAVASCRIPTapp.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:
JAVASCRIPTapp.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:
JAVASCRIPTapp.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.
BASHRequest: /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:
JAVASCRIPTapp.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:
JAVASCRIPTapp.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/
.
BASHnode 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:
JAVASCRIPTapp.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
:
BASHnpm install ejs
or using yarn:
BASHyarn add ejs
Then set the template engine to EJS:
JAVASCRIPTapp.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:
JAVASCRIPTimport 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:
JAVASCRIPTapp.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
- Getting Started with TypeScript
- How to deploy a .NET app using Docker
- Best Visual Studio Code Extensions for 2022
- How to deploy an Express app using Docker
- Learn how to use v-model with a custom Vue component
- Using Puppeteer and Jest for End-to-End Testing
- How to Scrape the Web using Node.js and Puppeteer
- Creating a Twitter bot with Node.js
- Getting Started with Vuex: Managing State in Vue
- Using Axios to Pull Data from a REST API
- Getting Started with Moon.js
- Getting Started with Vue