The ExpressJS framework is one of the simpler yet very powerful web frameworks for NodeJS.
It provides a simple way to expose
POST endpoints on your web application, which then serves
the appropriate response. Getting started with ExpressJS is easy and the Guides on the
ExpressJS website are very well written to make you effective in short order.
Moving towards a flexible app structure
When you have a simple app with a few endpoints, it is easy to keep everything
self-contained right inside of the top-level
app.js. However as you start
buliding up more
POST endpoints, you need to have an organization scheme
to help you manage the complexity. As a simple rule,
When things get bigger, they need to be made smaller ;–)
Fortunately, several smart folks have figured this out earlier and have come up with approaches that are wildly successful. Yes, I am talking about Rails and the principle of “Convention over Configuration”. So lets apply them to our constantly growing app.
Most of the routes (aka restful endpoints) that you expose on your app can be logically grouped together, based on a feature. For example, if you have some endpoints such as:
… you can try grouping them under the “login” feature. Similarly you may have other endpoints
dedicated to handle other workflows in your app, like uploading content, creating users, editing
content, etc. These kind of routes naturally fit into a group and that’s the first cue for
breaking them apart. As a first step, you can put the logically related
POST endpoints in
their own file, eg: login.js. Since you may have several groups of routes, you will end up with
lots of route files.
Putting all of these files at the top-level is definitely going to cause a clutter. So to simplify this further, put all of these files into a sub-folder, eg: /routes. The project structure now looks more clean:
1 2 3 4 5 6 7
Since we are working with NodeJS, each file becomes a module and the objects in the module can be
exposed via the
exports object. We can establish a simple protocol that each route module must
init function which we call from app.js, passing in the necessary context for the route.
In case of the login this could look like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
If you are using a recent version of ExpressJS,
2.5.8 as of this writing, the command-line
interface provides a way to quickly generate the express app. If you type
name-of-the-app, it will generate a folder named
name-of-the-app in the current working directory. Not surprisingly, express creates the /routes folder for you, which is already taking you in the right direction. I only learnt this recently and have so far been doing the hard work of starting from scratch each time. Sometimes spending a little more time on the manual helps! RTFM FTW.
Once we have the route files as described, it is easy to load them from
app.js. Using the
filesystem module we can quickly load each module and call
init() on each one of them. We do this before the app is started. The
app.js skeleton looks like so:
1 2 3 4 5 6 7 8 9 10 11
Now we can just keep adding more routes, grouped in their own file and continue to build several endpoints without severerly complicating the app.js. The app.js file now follows the Open-Closed-Principle (app.js is open for extension but closed for modification).
As you can see, it is actually a simple idea, but when applied to other parts of your application, it can substantially reduce the maintenance overhead. So in summary:
- Establish conventions to standardize a certain aspect of the program. In our case it was routes.
- Group related items into their own module
- Collect the modules into a logical folder and load from that folder