16. Using MVC directory structure

Like any application, how we organize our API code is important for ease of use.

We're going to use the MVC architecture for the server app i.e. "model, view, controller". You'll see as we progress that this is a logical and simple approach.


Let's begin by setting up the first controller. We'll create a new folder called controllers, and create a file items.js which will hold the logic for any route that loads items.

$ mkdir server/controllers
$ touch server/controllers/items.js

With that done, we're now going to cut the callback method from our GET /items endpoint, and put it in the new file.

We'll assign this method to exports.list.

We do this because this file is a CommonJS module, and adding properties to the exports object will allow us to call them from other files.

We'll call this particular function list since we call it to get a list of items, as we'll soon see.


exports.list = (req, res) => {
  res.send({ message: "It works!" });


Next we're going to create a router file as well. This file will be used to link our HTTP request to the corrosponding controller method.

So lets go:

$ mkdir server/routes
$ touch server/routes/items.js


At the top of the file, we load Express, and then we create an instance of the Express router. This object makes it easy to create a well-organized collection of routes as you'll see in a moment.

We also load the controller module we just created.


const express = require("express");
const router = express.Router();
const ItemsController = require("../controllers/items");

Now we can use the router object and call the route method to define a route. This takes one argument, which is the route URI. We're going to use the URI "/", not "/items".

That's because this file will be used for any route that is a child of the sub-path "/items", e.g. "/items/id" or whatever.

Next, we can load a controller method for the corrosponding HTTP method, and we pass in the controller method.

Finally, at the bottom of the file, we export the router from the file so we can also use the router as a CommonJS module.



module.exports = router;


The last step is to load the router in our main script. Remove the existing route code from this file and instead add this:


app.use("/items", require("./routes/items.js"));

What this does is to assign the router we just created to the sub-path /items.

With that done, we now have a much more robust architecture for our app. You'll see shortly that this is a really effective way to organize our API code.

Let's test this and make sure everything works. We'll turn on the server again.

Then we'll go to Postman and test our endpoint again. You should find it works exactly before!