Working with MEAN: getting started
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:
- MongoDB - MongoDB is an open-source, document database designed for ease of development and scaling, using Mongoose JS used as ORM to access MongoDB
- Express JS - Fast, unopinionated, minimalist web framework for Node.js
- Angular JS - HTML enhanced for web apps
- Node JS - Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine
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
, andserver.js
files in the project root./
. Theserver.js
references custom modules inapp/
directory by convention. - for express JS: the
app/
containsapp/routes.js
containing the various routes needed to run the back end API of our app - for MongoDB: the
server.js
orapp/routes.js
references model objects inapp/model/
using Mongoose JS used as ORM to access MongoDB data - for Angular JS, the
public/
runningpublic/index.html
containing angular directives and referencing javascript libraries supplied by bower in./bower.json
inpublic/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