DEV Community

loading...
Cover image for Organizing with express.Router()

Organizing with express.Router()

James Easter
Creative, coffee-drinking software developer
・5 min read

To Router() or not to Router()?

Over the last several applications that I have been working on I noticed just how useful express.Router() can be. I also noticed that I don't always use it. In fact, on some apps, I forget it exists.

So when is it useful and to what extent? Glad you asked! We'll examine when it can be helpful and why, along with some code snippets that will get you on your way to using express.Router() the next time you need it.

Let's start with what is this router object. Express's documentation gives us three important short paragraphs to ponder:

  1. A router object is an isolated instance of middleware and routes. You can think of it as a β€œmini-application,” capable only of performing middleware and routing functions. Every Express application has a built-in app router.

  2. A router behaves like middleware itself, so you can use it as an argument to app.use() or as the argument to another router’s use() method.

  3. The top-level express object has a Router() method that creates a new router object.

To summarize, an express router is an object that performs middleware and routing functions and behaves like middleware. Router() creates new instances of this object.

I'm not sure my summary was any more clear but once we look at the application we'll be able to see all of this in action.

To begin let's start with a basic express server setup:

const express = require('express')
const app = express()
const port = 3000

// Respond with Hello World! on the homepage:
app.get('/', (req, res) => res.send('Hello World!'))

app.listen(port, () => console.log(`App listening at http://localhost:${port} πŸš€`))

If you fire up the server with $ node your_server_filename or if you use the VSCode debugger (my personal preference) then you should see "Hello World!" in your browser when you go to http://localhost:3000.

Now let's think on down the line for this application when you are wanting to handle API requests and from your frontend to render and manipulate different data from your database. Woh! That was a big step. And I guess that is kind of my point. If you are building a small app to try out new tech, experiment with a new frontend, or test out a new database management system then setting up an entire system for handling API routes with express.Router() may be overkill.

However, if you are working on an application with several other developers and have a lot of API requests coming in, this could be your lucky day, new best friend, and your favorite post.

For a quick example, let's pretend we have users, messages, and posts in a database for a social media app we are building. Now at different points we will need to make api requests to our server for this information. To try this out we can utilize Postman to make api calls to our server.

Let's add the following to our server below our current get request handler and above our app.listen:

// Respond to a GET request to the /api/users route:
app.get('/api/users', (req, res) => res.send('Got a GET request at /api/users'));

// Respond to a PUT request to the /api/users route:
app.put('/api/users', (req, res) => res.send('Got a PUT request at /api/users'));

// Respond to a DELETE request to the /api/users route:
app.delete('/api/users', (req, res) => res.send('Got a DELETE request at /api/users'));

This only covers the /api/users route... We said we were going to handle users, messages, and posts. As you can see this will clutter our server file, quickly making it an extensively long amount of code that we'll have sift through and try to keep clean.

OR......

We could break up this code and organize it into a few files that are clean and easy to find. Yes, I like the sound of that.

Please welcome, the express.Router() to the stage!

First lets create a folder called "api" that is next to our server file, my server file is called index.js and is in a folder called server. Then let's add an index.js file to the "api" folder followed by these files in the same folder: users.js, messages.js, and posts.js. My file structure looks like this:

β”œβ”€β”€ server
β”‚   └── index.js
β”‚   └── api
β”‚       β”œβ”€β”€ index.js
β”‚       └── messages.js
β”‚       └── posts.js
β”‚       └── users.js

From here we will build out our routing functionality. I'm going to walk through the users api requests code and you can copy and paste accordingly for as many new api routers as you'll need.

Code to add to server/api/users.js

const { Router } = require('express');

// Handles requests made to /api/users
const usersRouter = Router();

// Respond to a GET request to the /api/users route:
usersRouter.get('/', (req, res) => res.send('Got a GET request at /api/users'));

// Respond to a PUT request to the /api/users route:
usersRouter.put('/', (req, res) => res.send('Got a PUT request at /api/users'));

// Respond to a DELETE request to the /api/users route:
usersRouter.delete('/', (req, res) => res.send('Got a DELETE request at /api/users'));

module.exports = {
  usersRouter,
};

Notice we changed app.get to userRouter.get because we are utilizing Router() from express. Also our url is just '/', this is because when we import this into server/api/index.js we'll pair this usersRouter with '/users'.

Here's what we'll add to the server/api/index.js file:

const { Router } = require('express');
const { usersRouter } = require('./users');

const apiRouter = Router();

apiRouter.use('/users', usersRouter);

module.exports = {
  apiRouter,
};

Again notice we are using apiRouter instead of app (similar to users.js) and we are using usersRouter as middleware here.

And finally let's remove the three request handlers we originally had inside of server/index.js and add two lines of code require the apiRouter and use it as middleware.

const express = require('express')
const app = express()
const port = 3000

const { apiRouter } = require('./api');

app.use('/api', apiRouter);

// Respond with Hello World! on the homepage:
app.get('/', (req, res) => res.send('Hello World!'))

app.listen(port, () => console.log(`App listening at http://localhost:${port} πŸš€`))

Again we have abstracted all of the api request handlers into the two other files and are now using one piece of middleware to handle all /api routes and keep this code nice and clean.

If your server file is starting to look big and scary express.Router() is there for you. Hope you enjoy clean code and clear routes!

Discussion (0)