ExpressJS: Static and Dynamic Routes

reiallenramos

Rei Allen Ramos

Posted on April 26, 2020

ExpressJS: Static and Dynamic Routes

Recently I've been writing simple VueJS tutorials. This got me thinking -- wouldn't it be better if I also had a backend that complements Vue? Several articles later, I was convinced that ExpressJS is just what I need.

This tutorial:

  • will generate a bare-bones ExpressJS server app
  • will discuss how to write a simple ExpressJS API (GET)
  • will demonstrate how to convert a static route to a dynamic one
  • will not discuss the complete RESTful verbs (POST, PUT, PATCH, etc)

Project Setup

mkdir express-routing-practice && cd express-routing-practice
npm init -y
npm i --save express debug http

This will generate package.json and package-json.lock for us. We'll need the debug and http modules because it's required by bin/www (more details later).

Express Setup

For this tutorial, I don't recommend using the Express generator because it creates a lot of boilerplate code that we won't use. What we'll do is use it as a guide to bootstrap our app. This also helps identify which sections of the Express generator is directly related to routing.

Create a bin folder and an empty file www.

mkdir bin && cd $_
touch www

Copy this from the official repo to bin/www to do the heavy lifting. We don't need to delve in detail what each line does. However we do need to note that var app = require('../app') tells us which file is our entry point. Let's create that file now via touch app.js in the root folder, then add the following:

// app.js
var express = require('express');
var app = express();

module.exports = app;

Update package.json to remove the default entry point index.js and add a new script to start our server:

// before
{
  "name": "express-routing-practice",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
...
}

// after
{
  "name": "express-routing-practice",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "DEBUG=express-routing-practice:* node ./bin/www",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
...
}

Then in your terminal, start your server via npm start. Visit localhost:3000 in your browser. If you're seeing Cannot GET /, that means our server is operational! 🎉

Create a GET endpoint

We'll create 2 routes with 1 GET endpoint for each. Create a new folder and the 2 files via:

mkdir routes
touch routes/home.js
touch routes/users.js

home route

Open home.js and paste the following:

var express = require('express');
var router = express.Router();

// Explanation: A nameless path GET request without any parameters.
// We'll learn how to name a path in users route.
router.get('/', function(req, res, next) {
  return res.json({ message: 'Home!', data: null })
});

module.exports = router;

Then add this to app.js anywhere before module.exports = app; to use it:

// Explanation: requests to `localhost:3000/` should be redirected to `routes/home.js`
var homeRouter = require('./routes/home')
app.use('/', homeRouter);

Restart your server then visit localhost:3000 to see the json on screen!

users route

Setup users.js and add some data:

var express = require('express');
var router = express.Router();

var data = [
  {
    name: 'Bibi',
  },
  {
    name: 'Colt',
  },
  {
    name: 'Jessie',
  }
]

router.get('/', function(req, res, next) {
  return res.json({ message: 'Users Index', data: data });
});

module.exports = router;

then update app.js to include:

var usersRouter = require('./routes/users');
app.use('/users', usersRouter);

Restart server, visit 'localhost:3000/users' and see the data come to life.
Tip: You can also use cURL to test your endpoints. We're making an API after all 😄.

Adding path name to a GET endpoint

By convention, a GET endpoint will return a complete list (or an index) of a resource. But should you need to set another GET endpoint, Express is ready for that.
Let's build on top of users.js to create more GET endpoints:

router.get('/Bibi', function(req, res, next) {
  var name = req.originalUrl.split('/')[2];
  var user = data.filter(u => u.name == name);
  return res.json({ message: 'User Show', data: user });
});

router.get('/Colt', function(req, res, next) {
  var name = req.originalUrl.split('/')[2];
  var user = data.filter(u => u.name == name);
  return res.json({ message: 'User Show', data: user });
});

router.get('/Jessie', function(req, res, next) {
  var name = req.originalUrl.split('/')[2];
  var user = data.filter(u => u.name == name);
  return res.json({ message: 'User Show', data: user });
});

Explanation: a GET request to localhost:3000/users/Bibi will be redirected to the subpath Bibi, and so on.

Whoa there! Our reference data didn't change but our source code just scaled in size! Imagine if we had 99 objects in the data array -- will we make 99 subpaths? Well technically we can but wouldn't it be better if there was a way to encapsulate all these subpaths?

Dynamic routes

What we've created up until now are called static routes. To convert these into a dynamic route, we simply need to declare an identifier using a colon (:). Express then automagically determines which subpath the request should be redirected to.
Updating the three subpaths:

router.get('/:name', function(req, res, next) {
  var name = req.params.name;
  var user = data.filter(u => u.name == name );
  return res.json({ message: 'Users Show', data: user });
});

Hooray! Now you'll be able to access localhost:3000/users/Bibi, localhost:3000/users/Colt, and localhost:3000/users/Jessie using one dynamic route 🎉!

💖 💪 🙅 🚩
reiallenramos
Rei Allen Ramos

Posted on April 26, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related