FusionWorks
Published in

FusionWorks

Set up a smarter routing system with Node.js and Express

At FusionWorks we enjoy using the NestJS framework, which helps a lot to keep our Node.js code clean and well-structured thanks to its modular architecture. But what if you only have Express at a hand? Could we achieve something similar?

In this tutorial, we’ll set up routes with “dummy” handler functions. On completion, we’ll have a modular structure for our route handling code, which we can extend with real handler functions. We’ll also have a really good understanding of how to create modular routes using Express!

Let’s say we have three routes (/, /home, /about), each one with two different HTTP verbs (get, post).

Our goal here is to create a separate file for each path and make use of the Express Router object. The Router object is a collection of middleware and routes. It is a mini-app within the main app. It can only perform middleware and routing functions and can’t stand on its own.

// routes/root.js
const express = require("express");
const router = express.Router();
router
.route("/")
.get((req, res) => res.send("getting /"))
.post((req, res) => res.send("posting /"));

module.exports = router;
// routes/home.js
const express = require("express");
const router = express.Router();
router
.route("/home")
.get((req, res) => res.send("get /home"))
.post((req, res) => res.send("post /home"));

module.exports = router;
// routes/about.js
const express = require("express");
const router = express.Router();
router
.route("/about")
.get((req, res) => res.send("get /about"))
.post((req, res) => res.send("post /about"));

module.exports = router;
// index.js
const express = require("express");
const app = express();
const port = 3000;
app.use("/", require("./routes/root"));
app.use("/home", require("./routes/home"));
app.use("/about", require("./routes/about"));
app.listen(port, () =>
console.log(`App listening at http://localhost:${port}`)
);

By having each route in its own file, we’re achieving a less messy code in the index.js file. The problem that still persists here — is that every time we add a new route file, the main file has to change as well, in order to map the path to the file.

Achieving a greater number of routes — produces the same problem: the main file gets bigger and messier.

We can solve this issue by creating a separate file that maps all the other routes and making use of it inside the main file.

// routes/index.js
module.exports = (app) => {
app.use("/", require("./root"));
app.use("/home", require("./home"));
app.use("/about", require("./about"));
};
// index.js
const express = require("express");
const app = express();
const port = 3000;
const bootstrapRoutes = require("./routes");
bootstrapRoutes(app);
app.listen(port, () =>
console.log(`App listening at http://localhost:${port}`)
);

The routes folder index file receives the app instance from the main file and makes the path mapping. Now we have a cleaner main file, but we still have the problem that it’s required to manually map each path to its file.

This can be improved if we would loop through the routes folder’s files and map them accordingly. We’ll be using the filesystem readdirSync method. This method is used to synchronously read the contents of a given directory,
it also returns an array with all the file names or objects in the directory.

// routes/index.js
const snakeCase = require("lodash/snakeCase");
const express = require("express");
const fs = require("fs");
const path = require("path");
module.exports = (app) => {
const files = fs.readdirSync(__dirname);
files.forEach(file => {
if (file === "index.js") {
return;
}
const filePath =
file !== "root.js"
? file.replace(".js", "")
: "";

const router = express.Router();
const currentRoute =
require(path.join(__dirname, `/${filePath}`))(router);
app.use(`/${filePath}`, currentRoute);
});
}

References

--

--

--

FusionWorks is a software development company that focuses on outsourcing services, full-cycle product development and IT community building. The company was founded in 2011 by Genadii Ganebnyi and Anton Perkin and has its headquarters in Moldova. More at https://fusion.works

Recommended from Medium

Jumping into React, Node, MongoDB, and AWS S3

Webpack or SystemJS, tell me which one is the better

Full-stack React + GraphQL Tutorial

Make a HTML element editable with contenteditable ✨

JavaScript How to: check if a variable holds an object

How We Deploy React Native App | Hosting Services | Cloud Hosting Services | Free Hosting Services

JOI To the World

How to Use Objects Like Arrays in JavaScript

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Vlad Gorea

Vlad Gorea

More from Medium

Creating and Managing Virtual Domains using Node.js

Build an Uploading Service to S3 using NodeJS and TypeScript

Creating A NodeJS RESTful API without ExpressJS — Part 2

Creating A NodeJS RESTful API without ExpressJS — Part 2 — adding crud operations to the API

It’s all about NodeJS