Organizing your application structure and its routes is one of the first problems you will encounter while developing with Express. To help you with that version 4 added the Router class.
Let’s use it to define some routes in a cars.js file.
You define the brands and the models routes and then you export the entire router, so that you can use it elsewhere. It makes defining controllers in an MVC style app much more modular. Moreover, it will later help you when you build larger more complex applications.
Let’s load your new routes in an Express app.
This app will respond to /cars/brands or /cars/models requests, with the data you defined above.
The most important bit, from the app file above, is
It loads the router with its routes and defines a prefix for all the routes loaded inside. The prefix part is optional. You could write for example
Then the server will respond only to requests from /brands and /models.
Using the routers for structuring your app
Let’s use those features in a bigger MVC app with the following file structure:
cars.js will be the same as above and animals.js will define a few more routes.
Again, you define the routes and then the router is exported, nothing new.
Your next file controllers/index.js will be responsible for loading all controllers, which you’ve already implemented. It will also define some more routes but without prefix, like a home page and an about page.
Every router can load other routers. This is very handy when you are organizing your app. You can even build a hierarchy of routers and routes, if you really need it.
I prefer to keep it only one level deep as in the example above, but your needs may vary.
In the file above, you first include your existing routers with their routes and then you define two more routes, before as usual to return the current router which contains all routes.
To load them, you only need to load the controllers/index.js file. Moreover, it is an index file, so you don’t need to provide its name when requiring it, you only need the folder name.
This is all you need to begin serving all routes defined in all your controllers. Your app will be responding to requests to the following paths.
- /
- /about
- /animals/domestic
- /animals/wild
- /cars/brands
- /cars/models
Notice how easy is to organize your routes with the Router class. All dependencies are only in one direction, from the base controller to leaf routes and routers.
Routers don’t know where they are used, they only know the routers they themselves include. This greatly simplifies dependencies and also makes the code more maintainable.
Router specific middlewares
Middlewares in express are extremely useful. They can load sessions, extract useful data, put common headers and much more.
While most of the time you add middlewares for the entire app with app.use, sometimes it is also useful to have them only for some routes. In such cases you would usually add the middleware to every individual path definition.
In larger more complex apps, having to add the middleware to each individual route quickly becomes tedious. In such cases you can add the middleware directly to the router.
The middlware will be executed only for all routes defined in this router and only for them. This can be used for defining whole controller authorization or making some input data transformation which will be then used everywhere inside the router or another common task.
Other benefits
The benefits of using routers will be felt on the all parts of your project. Separating the controllers with their own routers makes them more modular and easier to test.
You can also move around your controller both inside your file structure and in your path hierarchy, without affecting your code. All of this makes maintaining your application and working with larger team easier.
What’s next
If you are starting a new project you can clone the base-express repository from GitHub and use it as your starting point. It is already using the patterns shown above and it has a few more handy stuff. It is also always up to date with the latest version of Express and the latest versions of a few other libraries.
If you already have an existing app and you would like to use the Router class, I strongly recommend to first update to the latest express. Then rewrite the parts of your code that need rewriting. It will be easier and faster than you think. It will also result in much cleaner code and structure which is also easier to test and maintain.
Other articles that you may like