paint-brush
File-Based Routing in Node.js: A Brief Guideโ€‚by@dsitdikov
2,602 reads
2,602 reads

File-Based Routing in Node.js: A Brief Guide

by Daniil SitdikovSeptember 1st, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

About a year ago, I tried Next.js for the first time and was so impressed by their file-based routing that I decided to implement a similar system on backend
featured image - File-Based Routing in Node.js: A Brief Guide
Daniil Sitdikov HackerNoon profile picture

About a year ago, I tried Next.js for the first time and was so impressed by their file-based routing that I decided to implement a similar system on the backend. I couldn't find anything suitable, so I took it upon myself to create my own solution. It turned out to be technology-agnostic and works with both pure Node.js and the popular Express.js.


In this brief guide, we will attempt to partially implement a shop's API. This tutorial uses JavaScript and CommonJS module types to keep things simple and quick to get started.

1. Installation

๐Ÿ’ฟ Install :
npm install node-file-router

2. Initialization

Create a server.js file and do the following:

If you use pure Node.js:
// 1. Import default http module and node-file-router
const http = require('node:http');
const { initFileRouter } = require('node-file-router');

// 2. Create an entry-point function
async function run() {
  // 3. Initialize node-file-router and the handler function
  const useFileRouter = await initFileRouter();

  const server = http.createServer((req, res) => {
    // 4. Create a server and invoke created function on each request
    useFileRouter(req, res);
  });

  // 5. Start listening a server on 4000 port
  const port = 4000;
  server.listen(port, () =>
    console.log(`Server running at //localhost:${port}/`)
  );
}

// 6. Run entry-point function
run();
If you use Express.js:
const { initFileRouter } = require('node-file-router');
const express = require('express');

async function run() {
  const fileRouter = await initFileRouter();

  const app = express();

  app.listen(4000);
  app.use(fileRouter);
}

run();

2. A first route

๐Ÿก We will create a home route that displays welcome content.

1. Create an api folder at the root of your project.

โ”œโ”€โ”€ api/ <-
โ”œโ”€โ”€ server.js
โ””โ”€โ”€ package.json

2. Create a file named index.js inside this folder:

โ”œโ”€โ”€ api/
โ”‚  โ””โ”€โ”€ index.js <-
โ”œโ”€โ”€ server.js
โ””โ”€โ”€ package.json
module.exports = function index(req, res) {
  res.end("Welcome to our shop!");
}

3. Run a server using: node server.js command 4. Open a browser and navigate to //localhost:4000. You should see the message Welcome to our shop! displayed.


Congratulations! ๐ŸŽ‰ You've created a first file route

3. Add HTTP methods

1. Before we start, we need a small utility function that will parse JSON from a request. Create a folder utils and put http.utils.js the file inside.

โ”œโ”€โ”€ api/
โ”œโ”€โ”€ ...
โ”œโ”€โ”€ utils/
โ”‚  โ””โ”€โ”€ http.utils.js <-
...
module.exports = {
  parseJson(request) {
    return new Promise((resolve, reject) => {
      let data = '';

      request.on('data', (chunk) => {
        data += chunk;
      });

      request.on('end', () => {
        try {
          const parsedData = JSON.parse(data);
          resolve(parsedData);
        } catch (e) {
          reject(e);
        }
      });
    });
  }
}

2. Create a folder called products and an index.js file inside it.

โ”œโ”€โ”€ api/
โ”‚  โ”œโ”€โ”€ products/ <-
โ”‚  โ”‚  โ””โ”€โ”€ index.js <-
โ”‚  โ””โ”€โ”€ ...
...

3. Implement get and post methods:

const { parseJson } = require('../../utils/http.utils');

module.exports = {
  get: (req, res) => {
    res.end('list of products');
  },
  post: async (req, res) => {
    const newProduct = await parseJson(req);
    res.end(`a product will be created: ${JSON.stringify(newProduct)}`);
  }
}

3. Open a browser and go to . You should see a list of products message displayed.


4. Make a POST request using curl, Postman or any tool you like on . The response should display a product will be created along with your content.


Perfect! ๐ŸŽ‰ Let's move on

4. Dynamic routes

1. Create a new file with the name [id] inside the product folder.

โ”œโ”€โ”€ api/
โ”‚  โ”œโ”€โ”€ products/
โ”‚  โ”‚  โ”œโ”€โ”€ ...
โ”‚  โ”‚  โ””โ”€โ”€ [id].js <-
โ”‚  โ””โ”€โ”€ index.js
...


2. Fill it the same way as you did before:


module.exports = {
  // Add the `routeParams` argument as the final argument to the function. This argument will contain
  // all the taken route parameters.
  get: (req, res, routeParams) => {
    const { id } = routeParams;
    res.end(`product ${id} info`);
  }
};

3. Open a browser and go to . <br/> The page should display a message: product 123.


Alright, let's make it more sophisticated.

Say, we want to address the following case: /catalog/tag-1/tag-2/tag-n


4. Create a catalog folder with [[...categories]].js inside.

โ”œโ”€โ”€ api/
โ”‚  โ”œโ”€โ”€ catalog/
โ”‚  โ”‚  โ”œโ”€โ”€ ...
โ”‚  โ”‚  โ””โ”€โ”€ [[...categories]].js <-
โ”‚  โ”œโ”€โ”€ index.js
...

And add a single get method:

module.exports = {
  get: (req, res, routeParams) => {
    const { categories } = routeParams;

    // This type of route also covers just "/catalog"
    if (!categories) {
      return res.end('all products');
    }

    res.end(`get products that have such tags: ${categories}`);
  },
};
5. Open a browser and go to . The page should display a list of categories: men, sneakers, Nike.


๐Ÿฅ That's it!

What's next?


๋ฐ”์นด๋ผ์‚ฌ์ดํŠธ ๋ฐ”์นด๋ผ์‚ฌ์ดํŠธ ์˜จ๋ผ์ธ๋ฐ”์นด๋ผ