overview

what is the MEAN stack?

Mean is a tech stack for developing single page web apps with javascript on node js

This stack combines the following technologies:

Prerequisites

To configure and run the typical example found for instance from starter node angular project you will need to have installed

  • nodejs - to run javascript on the back end
  • [npmjs][npm] - to manage node js packages

basic architecture

To use this technology stack it is essential to install Node JS and the node package manager: npm

The basic architecture relies on node js to run a web server that exposes both the static site data featuring HTML with angular as well as server API routes Express connecting to MongoDB databases via Mongoose JS javascript based ORM.

starter projects and generators

To get started more quickly there are saveral starter apps and generators to use.

I followed the excellent starter node angular project on github to get started.

There are generators that help create more sophisticated production ready starters, including:

example application

Package Structure

From the starter node angular project, we have the following basic file structure

./
  app/
    models/
    routes.js

  config/

  public/
    bower_components/
    scripts/
      app.js
      controllers/
      services/

    views/
    index.html

  node_modules/
  .bowerrc
  server.js
  bower.json
  package.json
  README.md

Important aspects of the structure above

  • essential for Node JS is the package.json, and server.js files in the project root ./. The server.js references custom modules in app/ directory by convention.
  • for express JS: the app/ contains app/routes.js containing the various routes needed to run the back end API of our app
  • for MongoDB: the server.js or app/routes.js references model objects in app/model/ using Mongoose JS used as ORM to access MongoDB data
  • for Angular JS, the public/ running public/index.html containing angular directives and referencing javascript libraries supplied by bower in ./bower.json in public/bower_components library as configured via .bowerrc

Typical app layout and configuration

Looking at this example we can see the distiction between the back end run by node js and its modules managed by npm, and the front-end serving angular js and its dependent modules managed by bower.

back end configuration

Node JS configuration

for package.json (example)

{
  "name": "starter-node-angular",
  "main": "server.js",
  "dependencies": {
    "express" : "~4.5.1",
	"mongoose" : "~3.8.0",
	"body-parser" : "~1.4.2",
	"method-override" : "~2.0.2"
  }
}

example ‘main’ module

The server.js is configured in package.json to run as the main script. It is used to instantiate and configure the node js , and references other modules configured in package.json used for specific behavior.

Note the use of require() to load other modules for node that should have been downloaded via npm from the package.json ready to use. require() is also used to load the app custom modules as well.

for server.js as a generic example

// modules =================================================
var express        = require('express');
var app            = express();
var mongoose       = require('mongoose');
var bodyParser     = require('body-parser');
var methodOverride = require('method-override');

// configuration ===========================================

// config files
var db = require('./config/db');

var port = process.env.PORT || 8080; // set our port
// mongoose.connect(db.url); // connect to our mongoDB database (commented out after you enter in your own credentials)
mongoose.connect(db.url); // connect to our database

// get all data/stuff of the body (POST) parameters
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use(bodyParser.urlencoded({ extended: true })); // parse application/x-www-form-urlencoded

app.use(methodOverride('X-HTTP-Method-Override')); // override with the X-HTTP-Method-Override header in the request. simulate DELETE/PUT
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users

// routes ==================================================
require('./app/routes')(app); // pass our application into our routes

// start app ===============================================
app.listen(port);
console.log('Magic happens on port ' + port);           // shoutout to the user
exports = module.exports = app;                         // expose app

Database connection information for mongodb via mongoose

In server.js there is a module loaded called /config/db. We chose to use a seperate node module to contain the confgiutation to connect to the mongodb database.

For ./config/db.js

module.exports = {
	url : 'mongodb://localhost:27017'
}

and a connection to mongodb via mongoose can be made through the script

mongoose.connect(db.url); // connect to our database

the server.js also sets up express loaded as app in this example ready to listen to the configured port. Port could be supplied by the command line or defaults to 8080.

var port = process.env.PORT || 8080; // set our port

and then start express listenting on this port with with

app.listen(port);

front end app configuration

The front end confirguration centers around bower package manager loading packages for [angularjs][anglarjs] run single page application.

Bower configuration for the front end for angular JS app

In .bowerrc configure to use public/bower_components as the library

{
	"directory": "public/bower_components"
}

for bower.json (example)

{
  "name": "meantest",
  "version": "0.0.1",
  "dependencies": {
    "angular": "^1.3.0",
    "bootstrap": "^3.2.0",
    "angular-animate": "^1.3.0",
    "angular-cookies": "^1.3.0",
    "angular-resource": "^1.3.0",
    "angular-route": "^1.3.0",
    "angular-sanitize": "^1.3.0",
    "angular-touch": "^1.3.0",
     "tv4": "~1.0.15",
    "angular-sanitize": ">= 1.2",
    "objectpath": "~1.1.0"
  },
  "devDependencies": {
    "angular-mocks": "^1.3.0"

  },
  "appPath": "app",
  "moduleName": "testApp",
  "overrides": {
    "bootstrap": {
      "main": [
        "less/bootstrap.less",
        "dist/css/bootstrap.css",
        "dist/js/bootstrap.js"
      ]
    }
  }
}

essential starter app

NEXT

  • See the next article for a look at an example application
  • Go back to the top post to see the other articles