Creating an MVC Express.js Application

Express.js is probably currently the most popular Node.js framework for building web applications and APIs. It has a good history, a good community around it, lots of modules built for it, and a fairly solid reputation.

In what follows we’re going to walk through how to build an Express.js application using the Model View Controller (MVC) design pattern. It’s likely that we’ll do this tutorial in multiple parts.We’ll start out with a simple application structure and then we’ll move on by adding more complex concepts like authentication, dynamic routing, and reading from and writing to a database.

To start, it’s a good idea to have some background on both Node.js and Express so you know some of the terminology and philosophy behind what is being discussed. If you are not entirely familiar with Express.js there is an introduction to it here. And if you’re not entirely familiar with Node.js there is a primer on Node.js here.

At the time of this writing Express is at version 4.X. If you are reading this at a later point, it’s possible that the latest version differs quite significantly from this. Be sure to check out the Express.js homepage to find information on how to properly set things up using the most current version of Express. However, it may be the case that the steps followed in this tutorial will not be fully compatible with the most recent version of Express.js

package.json

To start we’re going to want to create a package.json file. You can read more about pakcage.json here. package.json will define some metadata type things like the name and version of the application, but most importantly, it will specify what modules you will need to download and run the application. You can read more about modules in Node.js here as well as in any good introduction to Node.js. Express is itself a Node.js module and it makes use of other Node.js modules. Some modules like “http” are core Node.js modules (part of the Node.js core) and some like express.js are third-party. Core Node.js modules will always be available to your application because it is running on Node.js

So our sample package.json file will look like the following…

{
    "name": "MVC-Express-Application",
    "description": "An Express.js application using the MVC design pattern...",
    "version": "0.0.1",
    "dependencies": {
        "express": "4.4.4",		
    }
}

One item of note: the name of any given package cannot have any spaces. This is to ensure that installation of packages is easy and consistent across all environments.If people were ever wanting to install our application as a module on npm (if we ever put our application on npm) by running $ npm install MVC-Express-Application it would not work if the package was named MVC Express Application. If we ran $ npm install MVC Express Application, the CLI would get confused.

Now if we run the following from the directory where our package.json file resides

$ npm install

all of the dependencies that we have specified will be downloaded and installed into a “node_modules” directory. The great thing about this is that if we need to update the versions of our modules or add new ones, we can just add or edit this package.json file and run “npm install” again. The npm installer will figure out all of the files needed. We are limited to the modules we are installing right now, but we will be adding a lot more to this later.

Application

Next we’ll want to create an “app.js” file. This file is the kickoff/entry point of our application when it starts up. This is akin to the main() function you’d find in C++ or Java.

The first components we’re going to want to add are here…

var express = require('express');

This loads up the express module. We can now refer to it in our code.

A lot of the modules we’ll be loading up are part of the Express.js project itself. There are many useful items that our application will be utilizing at various times throughout our application. As is described in the Node.js documentation on modules, Node.js modules can be loaded via references to filenames so long as those filenames are not named the same as reserved core Node.js modules, e.g. the “http” module.

We will need to install the http and path modules (which are part of the Node.js core modules) as they will be important for our application.

var express = require('express');
var http = require('http');
var path = require('path');

We are going to want to use the Express.js set function to do certain things like set application constant values. We are going to want to set the port that our application will run through. To do this we can set our port as a constant using the set function. We can also use the “path” module in combination with the Express.js use function to set the directories from which static assets will be served. These include things such as images, CSS files, and front-end JavaScript files (such as jQuery) or anything else that our client-side views will need. So create a directory called “static” inside our main directory and update our app.js file to look like the following…

var express = require('express');
var http = require('http');
var path = require('path');
var app = express();

app.set('port', 1337);
app.use(express.static(path.join(__dirname, 'static')));

And finally, just as we had done in our Introduction to Express.js we can run our server through our set port…

var express = require('express');
var http = require('http');
var path = require('path');
var app = express();

app.set('port', 1337);
app.use(express.static(path.join(__dirname, 'static')));

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
}); 

Now if we were to run…

$ node app

We could see our app running. At this point, our app doesn’t really do much other than run the server, but we’re on our way.

Templating

To get our app to display things in the browser (the “view” part of our Model-View-Controller application), we are going to want to choose a templating engine to render variables that we process in our Express.js application out to views. There are many different templating engines out there. Jadeis a popular templating choice, but I’m going to use Express Handlebars which is based off of the Handlebars.js JavaScript templating library.

To install the express-handlebars module we are going to want to update our package.json file by adding a new item to the dependencies section…

{
    "name": "MVC-Express-Application",
    "description": "An Express.js application using the MVC design pattern...",
    "version": "0.0.1",
    "dependencies": {
        "express": "4.4.4",		
        "express-handlebars": "1.1.0"
    }
}

And we are going to want to run npm install again…

$ npm install

which will pull down the express-handlebars module.

We will start out by just adding basic templating, but we will likely go back and modify this later on to be a bit more sophisticated. We’ll first want to create a “views” directory for our views. So create a new directory and call it “views” and update our code to look like the following…

var express = require('express');
var http = require('http');
var path = require('path');
var handlebars  = require('express-handlebars'), hbs;
var app = express();

app.set('port', 1337);
app.set('views', path.join(__dirname, 'views'));

/* express-handlebars - https://github.com/ericf/express-handlebars
A Handlebars view engine for Express. */
hbs = handlebars.create({
   defaultLayout: 'main'
});

app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');

app.use(express.static(path.join(__dirname, 'static')));

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Notice how we are using app.set(‘views’, path.join(__dirname, ‘views’)); to tell our handlebars engine to look for views in this directory.

Following the documentation of the express-handlebars module, we will want to create a layout. A layout is kind of like a master view or parent view that will house all of our different views that we will load up depending on the route. We need all of the common HTML that is essential to any webpage — such as the <!DOCTYPE html> as well as and the <head> and <body> elements and anything else we might need. Adding these to each and every view definitely would not be most efficient approach and will lead to a lot of repetitive code. What if we ever have to make any changes to our main HTML structure? We would have to change each and every view file. This might not seem so bad if we only have a few views. However, if the size and complexity of our application were to grow and we had dozens or even hundreds of views, things would get out of hand pretty quickly.

Fortunately, there is a better way. With Express Handlebars we can use a “layout” which will serve as a common container for our views. Some more info on using layouts can be found here. So we need to create a directory called “layouts” inside of our views directory. After we do this, we can put a Main.handlebars file in our layouts directory that will serve as our layout…

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>MVC Express Application</title>
</head>
<body>

    {{{body}}}

</body>
</html>

We’re also going to want to create 2 different views that we’ll make use of later. Add a directory called “home” in the views directory and add 2 files…

Index.handlebars

<p>Welcome to the homepage</p>

Other.handlebars

<p>Welcome to other. This is a different route using a different view...</p>

Don’t worry too much about this syntax now. We’ll revisit the practical usage of these later.

Router

Once we put all of the items that we want into our app.js file and have our views set. We are going to want to create a router.js file. A lot of MVC application frameworks such as Laravel (PHP), ASP.NET MVC (.NET/C#) or Django (Python) have a router file, where you can set certain routes and tell the application which code to run depending the route that the user goes to. Express.js routing is discussed here here

So for example, if in our application we wanted to have a list of all books we might have a route that looks like the following…

app.get('/books', function(request, response){
    console.log('List of all books');
});

The callback function that we pass into our router will run whenever a user goes to that particular route (/books). Of course, we are going to be a lot more sophisticated with the functions we have running (we are going to call our controllers from here), but this is just a simple illustration to show how routers work.

Note the request and response arguments we are passing into our function. These two items are very important in Express,js and will contain a lot of useful information about the request sent by the client and the response that we are going to use to send data back to the client from our server.

And if we wanted to set a “details view” for each book depending on the book id our route would looks like the following…

app.get('/books/:id', function(request, response){
    console.log('Book details from book id ' + request.params.id);
});

Now if we were to go to the route “/books/4” we’d go to this route with the id 4. The id value will be available to us on the request object.

Setting up a bunch of different routes is all well and good for GET requests, but we’re going to also want to have a place for the client to send data to us — either via form submissions or AJAX requests or some other means. Fortunately, we can also easily create a POST route to receive data from the client and process it.

app.post('/books/add', function(request, response){
    console.log('Post route to handle the addition of a new book');
});

Express.js also has functions for PUT and DELETE requests.

So now that we have a basic overview of routing, let’s create a router.js file and put it in the main directory. In this file, add the following…

// Routes
module.exports = function(app){
    
    // Main Routes
    
    app.get('/', function(request, response){
    
    });

    app.get('/other', function(request, response){

    });   

};

As we can see here we have created 2 routes. One main route / and one route /other.

We also have to update our app.js and send the app object to the router. In app.js pass the app object we have been adding things to the router like so…

// send app to router
require('./router')(app);

We have seen in the router that we can send in a callback and have it be available to us whenever a user navigates to a particular route. It’s fine to do things this way, but as the number of routes we create grows, our router.js file is going to get pretty big. So to add a little bit of organization to our application, it’s probably a good idea to separate these callback functions out into separate controllers because we are using the Model View Controller (MVC) design pattern to create our application.

Controllers

Let’s call our controller “HomeController”. Create a directory called controllers and in that directory create a file called HomeController.js In HomeController, add the following…

exports.Index = function(request, response){
    response.render('home/Index');
};

exports.Other = function(request, response){
    response.render('home/Other');
};

We have added 2 controllers, one for each route in our router file. Notice the response.render function and what we are passing into it. Here we are telling express to use the views in the views/home directory and use the particular view found in there. So for the / route we are using the “Index.handlebars” view and for the /other route we are using the “Other.handlebars” view Both of these will use the Main.handlebars file as a layout, because this is what we specified in our app.js file.

So let’s update the router.js file to use our newly created controllers. Note that we need to add a reference to our controller in the.

var HomeController = require('./controllers/HomeController');

// Routes
module.exports = function(app){
    
    // Main Routes
    
    app.get('/', HomeController.Index);
    app.get('/other', HomeController.Other); 

};

Recall that we had created 2 different views earlier Index.handlebars and Other.handlebars. Now if we were to run our app with $ node app and if we navigate to localhost:1337 and localhost:1337/other we can see the different views being used for our different routes.

Passing Data to Views

Rending different views in response to different routes is a great start. However, it’s kind of bland if we are only rendering static content in each view. Let’s figure out how we can pass data to our views. Update the 2 views to the following…

Index.handlebars

<p>Welcome to the homepage of {{ title }}...</p>

Other.handlebars

<p>Welcome to {{ title }}. This is a different route using a different view...</p>

And let’s also update our HomeController.js file as well and attach the “title” property to the response object and pass that object to our view.

exports.Index = function(request, response){
    response.title = 'Hello World';
    response.render('home/Index', response);
};

exports.Other = function(request, response){
    response.title = 'Other';
    response.render('home/Other', response);
};

Notice how we are passing the dynamic data in “title” to the view by attaching it to the response object and we can see that this data is rendered out to our views using the {{ title }} syntax. We can name these properties anything we want (we could have just as easily written response.cheese), the names just have to match in our views e.g {{ cheese }}.

Now if we were to run our app and navigate to localhost:1337 and localhost:1337/other we can see the different views being used rendering our data

These properties are also available to our layouts files as well. So if we wanted to we could update our Main.handlebars file to display the title in the <title> tag found in the <head> section of our HTML document…

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>{{title}}</title>
</head>
<body>
 
    {{{body}}}
 
</body>
</html>

It is worth noting that it is probably not the best idea to add individual properties directly onto the response object (which could get pretty messy and unmaintainable pretty quick) so let’s pull all of our data into a single object that we’ll attach to the response. We’ll call this object “pageInfo.” So let’s update our controller to look like the following…

exports.Index = function(request, response){
    response.pageInfo = {};
    response.pageInfo.title = 'Hello World';
    response.render('home/Index', response.pageInfo);
};

exports.Other = function(request, response){
    response.pageInfo = {};
    response.pageInfo.title = 'Other';
    response.render('home/Other', response.pageInfo);
};

Fortunately, we don’t have to do anything as far as updating our views go. This is one of the nice things about separating different areas of functionality out into different places.

Obviously this is just a simple example. In a more complex application it would be here in our controllers where we might use a model object to connect to a database and get the data back from there. But that’s another tutorial for another day.

Partial Views

The express-handlebars module also supports “partial views.” What is a partial view? A partial view is merely part of a view within another view. That is, it’s a subset of HTML markup within a larger container layout. So an example of this might be a menu partial view with a list of links like “Home,” “About Us,” “Contact,” and others of the sort. This menu partial view can be referenced (included) in a larger view containing the <html> and <body> elements along with any other outer container <div> elements.

You may have seen the concept of partial views utilized in various way with other web languages. For example, you might see something like within another PHP file to include a menu. ASP.NET web forms has user cotrol .ascx files and ASP.NET MVC has it’s own implementation of partial views as well. They’re pretty common

So to do a partial with Handlebars create a folder in the views directory called “partials” and make a file called Menu.handlebars with the following in it…

 <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/about">About</a></li>
    <li><a href="/contact">Contact</a></li>
</ul>

And you can include a partial view within your layout by using the {{> Menu}} syntax (with the right angle bracket). So in our Main.handlebars ;layout we can have the following…

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>{{title}}</title>
</head>
<body>

    {{> Menu}}
  
    {{{body}}}
  
</body>
</html>

We just need to make sure that we use the correct name of our partial view. They need to match.

Like with layouts, partial views are also able to handle data passed to them from the controller code as well, so we could really put whatever we want in them. Can’t complain about that!

Summary

We have covered a lot in this tutorial already so this is probably a good place to stop for now. We have learned how to organize a simple Express.js application into an MVC type architecture, and create a router to handle routes, controllers to process data when the user navigates to a particular route, and views to render the items we want when we pass that data to the view. In the future, we will discuss more complex components of creating an Express.js application including middleware, reading and writing data to and from a database (the model portion of MVC) and abstracting more components of an application into configuration files. Feel free to download the files below and play around with them. Don’t forget to run

$ npm install

to install the modules set in the package.json file.

Download Files
, , 9bit Studios E-Books

Like this post? How about a share?

Stay Updated with the 9bit Studios Newsletter

13 Responses to Creating an MVC Express.js Application

  1. Jim Fuqua says:

    Thanks for going to the trouble of writing this tutorial. I know almost nothing about node and the tutorial was helpful.

    A couple of suggestions.

    I could not get the downloaded file to run without one change. I had to change the name of the “Main.handlebars” file to “main.handlebars”. I am not sure but believe the problem is in app.js on the line that says “defaultLayout: ‘main'”, but don’t know enough about node to be sure.

    Also for a total novice like me, it would be best to start with a very simple setup with source that will run. Then make a minimal changes that will still run with the source. And then other changes that will still run until the more complex completed program will run.

    Because of my total unfamiliarity I could not get my version copied and pasted from the explanation to run. I suspect the reason was something more than just the issue of the case of one file.

    Please take these comments in the spirit they are given — you must show and tell in simple runnable terms for people who know almost nothing about what you are doing.

    Jim

    • Ian says:

      Hi there Jim — Thank you for your comment. I just pulled the package down and tried to run it. One question, did you run $npm install before trying to do anything else (i.e. run $node app)? It runs fine for me after I did that. The last line of the post says “(Don’t forget to run $npm install to install the modules set in the package.json file)” If this is the issue perhaps I need to make this instruction more prominent. If it is not, could you perhaps give me a bit more info on your environment (e.g. OS, browser, Node.js version)? Hopefully we can get this resolved one way or another. 🙂

  2. Srinidhi says:

    Hi Jim Fuqua,

    This might be a late answer. But there is a typo in the layouts folder. Rename Main.handelbars to main.handelbars and try running the application. It should work.

  3. Ole says:

    Great tutorial. Thanks!

  4. aneeq says:

    how to start work on mvc tell me and how to install mvc in computer.

    • Ian says:

      Hi there aneeq — In this case, MVC is not something you install specifically… it’s just the design pattern we are using to structure our Express application. The only thing you need to install is Node.js and the dependencies defined in the package.json via npm.

  5. Peter says:

    Thanks for the post, I learned a lot.

    However, I got lost when you started updating response.pageInfo.title – I’m getting an error that says ‘cannot set property “title” of undefined’, which makes me think the response.pageInfo object needs to be created somewhere. Did I miss the part of the tutorial where you create that?

    Thanks

    • Ian says:

      Hi there Peter — You are right. I did have this step in the download package but it was not there in the tutorial. I have added it in. Thanks for pointing this out.

  6. kavitha says:

    Great tutorial!

  7. viranja says:

    Great tutorial, and kindly request from you update some post regarding “connect with database (ex:Mysql)”

  8. Forrest Welch says:

    Thanks so much for this tutorial man. Start learning design patterns about a week ago and it’s been a steep learning curve. This is the first tutorial I could find that was not too hard to understand but also not too basic. Quick question though:

    //from app.js, why do we need to include this?
    app.use(express.static(path.join(__dirname, ‘static’)));

    • iconic says:

      Hi Forest — Thanks for the feedback. That line is to specify a directory where you could link to static files (images, CSS, etc.). So if you put a style.css file in that directory and you could link directly to it in your view <link href=”style.css” rel=”stylesheet”>

Leave a Reply

Your email address will not be published. Required fields are marked *