MVC, Node, and Express: The Controller (Part 2)

Welcome to Part 2 of this series on exploring MVC architecture. In this part, we’ll be diving into how we implement the controller in Node and Express.

To recap, the Controller is the first layer in MVC and is responsible for handling user input, managing application logic, and interacting with the Model and View.

Starting the Server

If you’ve set up your first server or are about to get started, you have probably seen some code like this:

import express from "express";

const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Welcome to my server!');
});

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

This is probably the simplest possible server we can establish in Node and Express.

The controller is responsible for handling requests from a browser and returning that request with a response. For this server specifically, it’s listening for a request at the root address (‘/’) and when that request is made, it responds by sending the message: 'Welcome to my server!’.

It might not seems like much but websites are just collections of these routes. We could add another like so:

import express from "express";

const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Welcome to my server!');
});

app.get('/api', (req, res) => {
  res.send('Welcome the API page.');
});

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

It doesn’t take long to realize how messy this file can get as we continue to add more routes to our web server. Much in the same way that HTML, CSS, and Javascript are kept separate following separation of concerns, the routes for a server are also kept in a separate file. Let’s see what that looks like.

Separation of Routes

The first step is to replace our two app.get( ) statements with a single app.use( ) statement as shown below:

import express from "express";

const app = express();
const port = 3000;

app.use('/', require('./routes/index'))

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

This require statement tells our server to go looking for our routing logic in a separate file called index.js

Note: The .use( ) method is a type of middleware built into the Express framework known as the router. The router takes routes that would initially be declared in a single file, packages them as modules and allows them to be accessed by any file accessible to Express.

const express = require('express')
const router = express.Router()

router.get('/', (req, res) => {
  res.send('Welcome to my server!');
});

router.get('/api', (req, res) => {
  res.send('Welcome the API page.');
});

module.exports = router

Visually the organization looks like this:

And just like that, we have implemented a simple controller in Node and Express using best practices. Continue to Part 3 to see how this all connects with the second layer of MVC architecture, the model.

Previous
Previous

MVC, Node, and Express: The Model (Part 3)

Next
Next

Getting Started with MVC Design (Part 1)