Node.js/Express Convention-Based Routes 2


I’ve always been a fan of convention-based routing so I converted a local route generation script I’ve been using with Node.js/Express applications into an npm package called express-convention-routes. The package can be used to automate the creation of Express routes based on a directory structure.

What’s a convention-based Express route? It’s a route that is dynamically generated and associated with a “controller” function without having to explicitly code the route yourself (i.e. you don’t write code such as app.use(‘/foo’, router)). express-convention-routes creates routes automatically by parsing a convention-based folder structure such as the one below when the server first starts.
-controllers
    -customers
        -customers.controller.js
    -api
        -cart
            -cart.controller.js
    -index.controller.js

This allows application routes to be created without having to write any app.use() code to define the individual routes. Using the previous folder structure, express-convention-routes would create the following routes (and associate them
with the appropriate “controller” functions):

/customers
/api/cart   
/

Each folder contains a “controller” file that defines the functionality to run for the given route. For example, if you want a root route you’d add a file into the root controllers folder (index.controller.js for example). If you want an api/cart route you’d create that folder structure under the controllers folder (see the folder example above) and add a “controller” file such as cart.controller.js into the api/cart folder. You can name the controller files anything you’d like and they can have as many HTTP actions (GET/POST/PUT/DELETE, etc.) in them as you want.

To get started using the npm package, perform the following steps:

    1. Install the express-convention-routes package locally:
      npm install express-convention-routes --save
    2. Create a controllers folder at the root of your Express project.
    3. To create a root (/) route, add an index.controller.js file into the folder (you can name the file whatever you’d like). Put the following code into the file:
      
        module.exports = function (router) {
          router.get('/', function (req, res) {
              res.end('Hello from root route!');
          });
        };
      
    4. To create a /customers route, create a subfolder under controllers named customers.
    5. Add a customers.controller.js file into the customers folder (you can name the file anything you’d like):
      
        module.exports = function (router) {
          router.get('/', function (req, res) {
              res.end('Hello from the /customers route!');
          });
        };
      
    6. Once the routing folder structure is created, add the following code into your express server code (index.js, server.js, etc.) to load the routes automatically based on the folder structure in the “controllers” folder when the Express server starts:
      
        var express = require('express'),
            app = express(),
            router = require('express-convention-routes');
      
        router.load(app, {
          //Defaults to "./controllers" but showing for example
          routesDirectory: './controllers', 
      
          //Root directory where your server is running
          rootDirectory: __dirname,
          
          //Do you want the created routes to be shown in the console?
          logRoutes: true
        });
      
    7. Try out the included sample app by running the following commands:
      • npm install
      • npm start
    8. The sample app included with the package (see the Github project) follows a feature-based approach where the controller and associated view are in the same folder (handlebars is used for the views in the sample). If you prefer the more traditional approach where all of the views live in the “views” folder you can simply move the .hbs files there into the proper folders.

I originally got the convention-based routes idea from ASP.NET MVC (as well as other MVC frameworks) and KrakenJS (http://krakenjs.com). These frameworks automate the process of creating routes so I wanted to do something similar with express-convention-routes while keeping the dependencies as minimal as possible and the code as simple as possible.



Join the free Code with Dan Development Newsletter!

  • casualObserver43

    Great to see this, and agree this is a solid way for doing things at scale. What are your thoughts on a couple things related to this?

    – Have you used kraken before on express? They have an underlying module, express-enrouten, that does similar things. If you’ve played with it, are there any noticeable differences worthwhile in features?

    – I’ve seen a lot of discussion around organizing Node services similar to the change the web world has made by using a feature based approach (i.e. controllers, models and potentially views under one directory for a feature). do you know of any libs that would support this convention?

    • Thanks for reading through it.

      As far as Kraken, I started out using that a few years ago and really liked it overall. But, as updates came out I kept running into constant dependency issues where a child dependency wouldn’t work if I wanted to go with the latest version (Dust.js helpers at the time). So, I decided to simplify everything and go back to basics to avoid the conflicts I kept running into. I suspect they’ve ironed that out now but haven’t tried it for over 2 years. Their router does a very similar thing (plus more). I wanted something very bare bones and basic though for my routing which is why I finally decided to create this package.

      For feature-based views, I updated the sample with that actually since I like the idea of keeping the controller and view next to each other in a “feature” folder. You just need to add __dirname in front of the view name to load them from a folder where the controller lives:

      https://github.com/DanWahlin/express-convention-routes/blob/master/examples/controllers/customers/customers.controller.js