DEV Community

Dhinesh Kumar
Dhinesh Kumar

Posted on • Updated on

Organizing Express Routes with a Route Loader

Introduction

Express Js is one of the most widely used Node frameworks for developing web applications. Its robust features and minimalistic capabilities have made it popular with developers for its easy-to-use nature. However, as an application grows in complexity, organizing the code can become a challenge. Express doesn't impose any folder or architectural structure, which can lead to a cluttered and hard-to-manage codebase.

The Problem

As your application grows, the complexity of your API will grow in tandem. To organize your code, you may want to split up your routes into multiple files. You can structure your code based on technical responsibilities (e.g. controllers, models, services, utils, tests) or domain modules (e.g. users, orders, products). However, manually importing all your routes one by one into the app.js file is not ideal.

The Solution (using ESM)

The problem of splitting the routes into multiple files can be solved by using a Route Loader. A Route Loader is a function that takes a glob pattern and automatically imports all your route files. You only need to call the function once in your app.js file, and it will take care of the rest.


import { Router } from 'express';
import glob from 'fast-glob';
import fs from 'fs';
import path from 'path';

const BASE_DIR = path.join(__dirname, '..');

export default async function RouteLoader(globPattern) {
  let router = Router();
  let files = [];
  try {
    files = await glob(globPattern, { cwd: BASE_DIR });
  } catch (error) {
    console.error(error);
  }

  for (const file of files) {
    if (fs.statSync(file).isFile() && path.extname(file).toLowerCase() === '.js') {
      try {
        const routeModule = await import(path.resolve(file));
        router = (routeModule.default || routeModule)(router);
      } catch (e) {
        throw new Error(`Error when loading route file: ${file} [ ${e.toString()} ]`);
      }
    }
  }

  return router;
}

Enter fullscreen mode Exit fullscreen mode

With this Route Loader, you can split up your routes into multiple files and organize them in a way that makes sense for your application. You only need to call the RouteLoader function once in your app.js file.
Here's an example of using the RouteLoader function in your main Express application file (usually named app.js or index.js). Let's assume you have your routes organized in a directory called "routes", with each file representing a different endpoint or resource. You can use the RouteLoader function to load all these routes into your application with the following code:

const express = require('express');
import RouteLoader from './RouteLoader';

const app = express();

const routes = await RouteLoader('routes/**/*.js');
app.use('/', routes);

app.listen(3000, () => {
    console.log('Example app listening on port 3000!');
});

Enter fullscreen mode Exit fullscreen mode

Your router should be defined like this:

export default function (router) {
    // create a new user
    router.post('/api/users/create', passport.authenticate('jwt', { session: false }), async function (req, res) { 
        /** your route implementation here*/
    });
    return router; 
}

Enter fullscreen mode Exit fullscreen mode

In this example, RouteLoader will look for all files with a .js extension in the "routes" directory and its subdirectories and load them as routes into the Express application. The use method on the app object is used to mount the routes on a specific path, in this case, the root / path.
You can also organize your routes by domain modules, for example, you can have separate files for handling users, orders, and products in separate files within the "routes" directory:

routes/
|- users.js
|- orders.js
|- products.js

In this case, you can modify the RouteLoader function to look for routes in the routes directory only, rather than its subdirectories:
const routes = await RouteLoader('routes/*.js');

Conclusion

Organizing your routes is an important step in keeping your Express application maintainable and scalable. By using a Route Loader, you can split your routes into multiple files, making it easier to manage your codebase and quickly add new routes as your application grows.

Latest comments (2)

Collapse
 
andersondavid profile image
Info Comment hidden by post author - thread only accessible via permalink
Anderson David SF

I dont know if I want to do that hahaah but next.js do it and everybody say ok

Collapse
 
dhinesh03 profile image
Dhinesh Kumar • Edited

This article is intended for those who are curious about understanding the underlying workings, rather than those who solely depend on multiple libraries.

Some comments have been hidden by the post's author - find out more