A NodeJS Starter Repo

I threw together a little repo to build Node+Express webapps. Check it out on GitHub; read below for the story.

It’s very simple and comes in three flavors:

  • Master branch: installs Express and a few of its middlewares. It sets up a public directory with placeholders for CSS, JS, and image files. It sets up a couple basic routes, has a simple starter controller, and an extendable config file with a few prepopulated options. It does not set up a view engine, but the directory structure is there for it.
  • EJS: the above, but comes with the EmbeddedJS view engine configured and a few starter views already in place
  • Jade: like the EJS branch, but has Jade configured for the view engine; a few starter templates, includes, and page fragments are scaffolded out

Background

The other day, I had a friend send me a message: he wanted to build a daemon for one of his web apps that would use a RESTful API to communicate with various parts of his system. I’m not fully aware of his needs, but he told me that it was going to be a bunch of simple HTTP based commands. I told him that it sounded like a perfect use-case for Node. He laughed. “Okay,” he said, “where do I begin? I’ve never touched it before. Any frameworks or applications structures you’d recommend?” I felt his pain. Like me, he’s been doing PHP for years. NodeJS is a different approach to things; wrapping your mind around Node’s event-driven nature when you’ve been doing procedural PHP your entire professional life can be tricky indeed.

I told him about a few frameworks I’ve looked at, but admitted I hadn’t done a lot with them. But I was working on a very simple application and just showed him the source code, then walked him through it line-by-line. He thanked me and we went our separate ways. The next morning, he told me all about how he was reading from a Mongo datastore and was communicating with different devices (I’m being intentionally vague; his baby is still a work in progress and I don’t want to divulge his idea.) I’d love to pat my own back and talk about how I was such a great teacher, but he’s a really talented guy and could’ve done it without me. However, the little walkthrough I gave him helped me realize that all the Node apps I’ve built so far have followed this same pattern. This got me thinking:

  1. I could package this up and save myself time in the future when I build apps
  2. I could use this package as a reference guide when introducing other people to Node (I have a few curious coworkers in mind for this point)

I don’t know if there’s a “right way” to structure your apps when building Node, but it does resemble the structure I’ve seen in many different tutorials. If you have different ideas, I’d love to hear them in the comments.

Directory Structure

I’ll go over everything below in (painful?) detail, but first I want to go over the directory structure. It’s pretty straightforward:

/node-starter
-/app
---/controllers
-----AppController.js
---/views
---config.js
---routes.js
-/public
---/css
-----style.css
---/images
---/js
-----scripts.js
-package.json
-README.md
-server.js

There are two main files in the project root, package.json and server.js. Our trusty README is there too, which basically contains a more concise version of this blog post. There are two main directories here: /public, which is where all of the static frontend assets live (as you can see, CSS, JS, and images are already scaffolded); and /app, where the guts of the application live. We’ll delve into the /app directory a little later on. It would be helpful to clone down the repo before continuing so you can follow along as we dissect it.

Setting up with package.json

Every single Node application ever needs a package.json file. It contains a few important bits of metadata about the app and has a list of dependencies that need to be installed for the app to work. It’s pretty straightfoward, but here’s what it looks like:

{
  "name"        : "NodeStarter",
  "version"     : "1.0.1",
  "description" : "A seed repo with a directory structure and NPM modules I commonly use when building Node Apps",
  "main"        : "server.js",
  "author"      : "Beau Watson ",
  "link"        : "http://www.docwatson.net",
  "repository"  : "https://github.com/DocWatson/node-starter",
  "dependencies": {
      "body-parser"        : "~1.0.1",
      "express"            : "4.0.0",
      "method-override"    : "~1.0.0",
      "morgan"             : "~1.0.0"
    }
}

You should update the top elements with your own app information. You can see in the dependencies block that there are four modules we’ll be installing: body-parser, express, method-override, and morgan. (Fun fact: these four things all used to be part of the Express package until they got separated into their own parts in Express4.) Express is the big, important module, as it will handle all of our routing API stuff; the other three are middlewares that make working with Express a little nicer. Body-parser lets us easily read requests sent to our API, while method-override simulates some HTTP verbs so we can do things like PUT and DELETE. Morgan is a tool that logs requests to the console which is very nice to have during development.

You can get all of these nice little modules installed on your system by running the npm install command while in the project directory. This will create another directory, aptly-named node_modules, with all the source files for these modules - these are .gitignored by default. With those guys installed, we can start up the app by running node server from the command line.

But, what’s in server.js?

If you’ve ever used a PHP framework or CMS (I admit - I’m making the assumption that you have), you probably know that the index.php file bootstraps and runs the entire app through it. It will usually load a config file to read some settings, handle requests, and call the appropriate methods from the appropriate controller classes. In this case, server.js is doing pretty much the same thing. Here’s its source:

//in /server.js
// set up ======================================================================
// the current environment (use `dev` or `production`)
var env      = 'dev';      

// Include the config file               
var config   = require('./app/config.js');
  // Include the express library
var express  = require('express');
// Set up the express app
var app      = express();                             
// Use the port set in the environment's config
var port     = process.env.PORT || config[env].port;  // set the port


// Include body-parser (allows us to read requests sent as json or urlencoded)
var bodyParser     = require('body-parser');

// Include method-override (allows us to use HTTP verbs PUT and DELETE)
var methodOverride = require('method-override');

// create the server and give it the express app
var server         = require('http').createServer(app);

// set a static dir (requests that match things in this dir will get served instead of invoking express)

app.use(express.static(__dirname + '/public'));

// If logging is set to true for the environment, use logging
if (config[env].logging === true) {		  
	// Include the morgan module for logging
  var logger   = require('morgan');
  // Set the Express app to use the logger (will output events to the console)
	app.use(logger(env));  
}

// Set the Express App to use the body-parser and method-override modules       
app.use(bodyParser());
app.use(methodOverride());


//* NOTE!=================================
//   You should configure a view engine here.
// Set the Express app's port
app.set('port', port);  

// Include the Routes module and pass it the Express app
require('./app/routes.js')(app);

// Start up the server at the given port
server.listen(app.get('port'), function () {	  
  // Display a message indicating successful launch and port
  console.log('App running at http://localhost:' + app.get('port'));
});

I won’t break it all down line-by-line because the comments above should hopefully accomplish that. But basically, what it’s doing is defining the environment (either dev or production), loading the config the for the environment, creating instances of all the modules we need and setting up the Express framework to use them. Towards the end of the file, we require the routes.js - we’ll get to it in a second - then we start up the server at our desired port. You can check it out at http://localhost:8080.

Hey! It crashed!

Yeah, you’re right! What gives? Well, the server crashes because it doesn’t have a view engine set up. You probably noticed that there was a note in the source about configuring one. We’ll talk about view engines and why the starter doesn’t have one configured towards the end of this post. Before that, we’re going to dig into the /app folder and see what’s going on there.

Configuring config.js

You’ll remember one of the very first things server.js does is load up the config file. The starter app on its own is small enough that a config file is probably overkill - but since it’s designed to be extended, having something scaffolded out seemed to be worth the time. Here’s the source:

// in /app/config.js
/**
* App Config
*
* @module      :: Controller
* @description	:: Some config options
*
*/

// expose the config to our app with module.exports
module.exports = {
  	dev : {
      logging : true,
      port    : 8080
    },

  	production : {
      logging : false,
      port    : 80
    }
}

I think the options speak for themselves, but I want to point out the module.exports line. Module.exports does about what it sounds like: it modularizes everything (which really amounts to a JSON object) so that Node can utilize it as a module. For example, in server.js, we loaded the config like so:

var config   = require('./app/config.js');

This means we can read the properties of config.js like we would any old JSON object. A console.log(config.dev.port) would output 8080. Pretty nice, huh?

Getting Routey

One of the more important files in the starter is routes.js. Here’s where our API logic lives - in other words: what happens when a specific HTTP request is made to a specific URL? Routes.js answers that question. In large apps, the routes will get very complex and should be broken up by function, but as a starter, it’s really quite lean:

//in /app/routes.js
// Include the AppController module that will handle any extra processing we need
var AppController = require('./controllers/AppController');

// expose the routes to our app with module.exports
module.exports = function(app) {
// api ---------------------------------------------------------------------
// Routing logic goes here (EG, GETs, POSTs, DELETEs, etc.)

// application -------------------------------------------------------------
// Render Index View
  app.get('/', function(req, res) {
    res.render('home');
  });

  // All other requests, send 404

  app.get('*', function(req, res) {
    res.render('404');
  });
};

You can see at the top of the file, we’re loading in a controller, but if you explore the code a little further, you’ll see that it’s not used anywhere. We’ll talk about the controller next, but we’ll look at the two pre-configured routes first. Notice both of them are using app.get(…) syntax - you can see that app is being passed into the module in the module.exports line. I wanted to point this out because this means you can set up your modules so that other things can be passed into them. If we refer back to server.js, you’ll see this where we’re including the routes.js module:

require('./app/routes.js')(app);

We are effectively handing the prepared Express object over to the routes module so that we can use Express’s methods inside of it. The two examples we have here are using Express’s GET handler. The first parameter is the route to match, and the second parameter is the callback function. This callback has two parameters of its own, req (the request object - which can be used sort of as an analog to $_GET and $_POST in PHP) and res (the response object - which is used to send responses back to the client).

The first route we have matches ‘/’, or the index page. It then uses the response object to render the home template. Of course, you’ll remember from above that we haven’t set up a view engine, so this will crash our app. The second app takes a wildcard ‘*’ and is set up so that if none of our routes are matched, we’ll render the 404 template.

You can do so much more with routes, but these types of things fall outside the scope of this guide.

A Controller scaffold

In the section above, we mentioned the AppController getting loaded, but it’s a bit of a red herring. As it stands right now, the AppController does absolutely nothing. It does so much nothing that I’m not even going to post its source code. It’s simply a module with an init function and nothing else. So why include it? Well, almost every app I’ve written so far does some sort of processing, and Controllers are the place to do it - application logic shouldn’t be inside of your routes or views. I set up the controller so that as the need arises, it will be there.

Okay, now we can talk about views

I’ve alluded to views and how the lack of them crash the app. I did not set up a view engine for a couple reasons. One, I want the developer to have the power to decide which view engine he or she may choose - it’s mostly a matter of personal preference. And two, there’s a chance you won’t even need a view engine at all. You may be writing an API service with no interest in rendering a view at all, for example.

However, if you want to start with a view engine already configured, I created a branch for two popular Node view engines: EJS and Jade. Each branch has starter templates in place, and while I’m not going to go over them here, the READMEs on each branch discuss them a little bit. Each view engine has its own set of docs that are pretty easy to follow - I encourage you to try both at some point. If you’re looking for one to start with, I’d recommend EJS. It stands for EmbeddedJS, and lets you write HTML with, well, embedded bits of JavaScript in the template to display variables. I think it’s pretty intuitive if you’re coming from a PHP or ASP.NET background (I think it also lends itself to Ruby as well, but don’t quote me on that). Jade takes a little getting used to as it uses shorthand html with Python-style tab delimination. It’s wonky and refreshing at the same time.

Get building!

So, we’ve pretty thoroughly dissected the starter app by now. Some of it might have been obvious to you from the get-go, but I was trying to limit my assumptions and approach this subject as Your First Node App. If something wasn’t obvious, let me know so I can clarify.

One final tip before we go: as you build an app, you’re going to want to add more NPM modules to it. You can easily install by using npm install <package_name> –save. That –save flag will automatically update your package.json file so you won’t have to. Isn’t NPM great? Now, go forth and build!