Saturday, August 6, 2016

How to Create a Complete Express.js + Node.js + MongoDB CRUD and REST Skeleton


Over the past few weeks I have created a few Node.js web apps (such as Bourbon Tweet Alerts) and I've noticed that there is a huge inconsistency in building Node.js web apps. I desperately needed a way to consistently build projects the same way every time. As we all know, there's nothing like having to figure out how someone made a piece of code function, much less an entire framework! I've been working with Ruby on Rails for a while, so making a transition into Node.js was quite a different leap. The one great thing I like about Rails is standardization. When you create a new rails app, the MVC architecture is templated out for you (ie "batteries included"). Node.js on the other hand, allows you to pick and choose any libraries you want to make the project successful. I've read over countless blogs and not a single one covers everything you need to know how to build a CRUD + REST application from soup to nuts. So I must thank about 20 different blogs and loads of github README's to help assemble this beacon of guidance.
I'll admit it, I'm a sucker for simple generation of skeleton. That's why I loved using rails. The entire MVC structure is laid out for me and I can be on my way.
  1. rails new myapp --database=postgresql
  2. rails generate scaffold Blob name:string badge:integer dob:date isloved:boolean
Generate the Express.js Skeleton

Within Node.js, the standard for creating web apps is Express.js. Express even has a template generator. Since you know I'm a sucker for it, let's use that. I'm going to assume you have Node.js & NPM already installed.
  1. npm install -g express
  2. npm install -g express-generator
Great. Now we've got Express & the generator installed as a global command on our system. To create a skeleton site go to your projects directory. When we create our application, a new folder with all the associated pieces are going to be created with it. By default this will use Jade as the html templating engine. There are other templating engines such as EJS, Mustache and Hogan, but once you start understanding Jade, it's very clean for simple web apps. Change out nodewebapp with whatever you want to call your application
  1. express nodewebapp
Yep, it was that easy. You should now see these lines start scrolling:
  1.    create : nodewebapp/app.js
  2.    create : nodewebapp/public
  3.    create : nodewebapp/public/images
  4.    create : nodewebapp/public/stylesheets
  5.    create : nodewebapp/public/stylesheets/style.css
  6.    create : nodewebapp/routes
  7.    create : nodewebapp/routes/index.js
  8.    create : nodewebapp/routes/users.js
  9.    create : nodewebapp/public/javascripts
  10.    create : nodewebapp/views
  11.    create : nodewebapp/views/index.jade
  12.    create : nodewebapp/views/layout.jade
  13.    create : nodewebapp/views/error.jade
  14.    create : nodewebapp/bin
  15.    create : nodewebapp/bin/www

  16.    install dependencies:
  17.      $ cd nodewebapp && npm install

  18.    run the app:
  19.      $ DEBUG=nodewebapp:* ./bin/www
Setup MongoDB

Do you have MongoDB setup? If you haven't, no worries. It's actually incredibly easy with your Mac and Homebrew.
  1. brew update
  2. brew install mongodb
Let's start our MongoDB server. Side Note: I prefer to use iTerm2 to have multiple tabs and windows with terminal prompts. From the terminal type mongod and you will see Mongo start up. By default, it will always use port 27017.
  1. kcoleman-mbp: kcoleman$ mongod
  2. mongod --help for help and startup options
  3. 2015-03-04T09:59:26.150-0500 [initandlisten] MongoDB starting : pid=13761 port=27017 dbpath=/data/db 64-bit host=kcoleman-mbp.local
  4. 2015-03-04T09:59:26.150-0500 [initandlisten] db version v2.6.7
  5. 2015-03-04T09:59:26.150-0500 [initandlisten] git version: nogitversion
  6. 2015-03-04T09:59:26.150-0500 [initandlisten] build info: Darwin minimavericks.local 13.4.0 Darwin Kernel Version 13.4.0: Sun Aug 17 19:50:11 PDT 2014; root:xnu-2422.115.4~1/RELEASE_X86_64 x86_64 BOOST_LIB_VERSION=1_49
  7. 2015-03-04T09:59:26.150-0500 [initandlisten] allocator: tcmalloc
  8. 2015-03-04T09:59:26.150-0500 [initandlisten] options: {}
  9. 2015-03-04T09:59:26.151-0500 [initandlisten] journal dir=/data/db/journal
  10. 2015-03-04T09:59:26.152-0500 [initandlisten] recover : no journal files present, no recovery needed
  11. 2015-03-04T09:59:26.184-0500 [initandlisten] waiting for connections on port 27017
From another terminal window, lets create a new database. We need to use the mongo client and 1 command to create it. Type mongo to enter the client/shell and use dbname. Of course change dbname to whatever name you want to call it. Here is the shell output.
  1. kcoleman-mbp:kcoleman$ mongo
  2. MongoDB shell version: 2.6.7
  3. connecting to: test
  4. > use nodewebappdb
  5. switched to db nodewebappdb
  6. > db
  7. nodewebappdb
  8. > show dbs
  9. admin               (empty)
  10. local               0.078GB
  11. nodews4             0.078GB
  12. nodewebappdb        0.078GB
  13. >
Setup Mongoose to MongoDB

We will need to install the dependencies before we fire up the server, but I like to make sure we get our database pieces sorted first. Open up your favorite editor, such as Sublime Text or Atom, and make a new folder within nodewebapp called model. Inside this folder create a new file called db.js. This is the file where we are going to place our database connections.
  1. var mongoose = require('mongoose');
  2. mongoose.connect('mongodb://localhost/nodewebappdb');
Next open up app.js and lets add our db.js file to the variables. by adding the line var db = require('./model/db'); 
  1. var express = require('express'),
  2.     path = require('path'),
  3.     favicon = require('serve-favicon'),
  4.     logger = require('morgan'),
  5.     cookieParser = require('cookie-parser'),
  6.     bodyParser = require('body-parser'),
  7.     db = require('./model/db'),
  8.     routes = require('./routes/index'),
  9.     users = require('./routes/users');
  10. ..
  11. ..
  12. ..
Install Dependencies

Now we need to install our dependencies. from the terminal of the working directory of nodewebapp type
  1. npm install
and you should see a big output
  1. kcoleman-mbp:nodewebapp kcoleman$ npm install
  2. debug@2.1.2 node_modules/debug
  3. └── ms@0.7.0

  4. cookie-parser@1.3.4 node_modules/cookie-parser
  5. ├── cookie-signature@1.0.6
  6. └── cookie@0.1.2

  7. morgan@1.5.1 node_modules/morgan
  8. ├── basic-auth@1.0.0
  9. ├── depd@1.0.0
  10. └── on-finished@2.2.0 (ee-first@1.1.0)

  11. serve-favicon@2.2.0 node_modules/serve-favicon
  12. ├── ms@0.7.0
  13. ├── fresh@0.2.4
  14. ├── parseurl@1.3.0
  15. └── etag@1.5.1 (crc@3.2.1)

  16. body-parser@1.10.2 node_modules/body-parser
  17. ├── media-typer@0.3.0
  18. ├── bytes@1.0.0
  19. ├── raw-body@1.3.2
  20. ├── depd@1.0.0
  21. ├── qs@2.3.3
  22. ├── iconv-lite@0.4.6
  23. ├── on-finished@2.2.0 (ee-first@1.1.0)
  24. └── type-is@1.5.7 (mime-types@2.0.9)

  25. express@4.11.2 node_modules/express
  26. ├── utils-merge@1.0.0
  27. ├── methods@1.1.1
  28. ├── cookie@0.1.2
  29. ├── fresh@0.2.4
  30. ├── range-parser@1.0.2
  31. ├── merge-descriptors@0.0.2
  32. ├── cookie-signature@1.0.5
  33. ├── escape-html@1.0.1
  34. ├── vary@1.0.0
  35. ├── media-typer@0.3.0
  36. ├── parseurl@1.3.0
  37. ├── finalhandler@0.3.3
  38. ├── serve-static@1.8.1
  39. ├── content-disposition@0.5.0
  40. ├── path-to-regexp@0.1.3
  41. ├── depd@1.0.0
  42. ├── on-finished@2.2.0 (ee-first@1.1.0)
  43. ├── qs@2.3.3
  44. ├── etag@1.5.1 (crc@3.2.1)
  45. ├── proxy-addr@1.0.6 (forwarded@0.1.0, ipaddr.js@0.1.8)
  46. ├── accepts@1.2.4 (negotiator@0.5.1, mime-types@2.0.9)
  47. ├── type-is@1.5.7 (mime-types@2.0.9)
  48. └── send@0.11.1 (destroy@1.0.3, ms@0.7.0, mime@1.2.11)

  49. jade@1.9.2 node_modules/jade
  50. ├── character-parser@1.2.1
  51. ├── void-elements@2.0.1
  52. ├── commander@2.6.0
  53. ├── mkdirp@0.5.0 (minimist@0.0.8)
  54. ├── with@4.0.1 (acorn-globals@1.0.2, acorn@0.11.0)
  55. ├── constantinople@3.0.1 (acorn-globals@1.0.2)
  56. └── transformers@2.1.0 (promise@2.0.0, css@1.0.8, uglify-js@2.2.5)
We need to add a few more packages to our package.json file as a dependencies. Mongoose will be our connection to MongoDB, body-parser is used to examine POST calls, and method-override is used by express to create DELETE and PUT requests through forms. read about method-override
  1. npm install mongoose --save 
  2. npm install body-parser --save
  3. npm install method-override --save
Awesome. Now to test it's all working in the terminal type npm start and you shouldn't see any errors:
  1. kcoleman-mbp:nodewebapp kcoleman$ npm start
  2. > nodewebapp@0.0.1 start /Users/kcoleman/Documents/projects/nodewebapp
  3. > node ./bin/www
and if you navigate to http://127.0.0.0:3000 you will see the following screen


HOORAY!

We've got a functioning web server that is talking to Mongo. Part 1 is accomplished.
Coming from a Rails background, it was pretty easy to create a new model with all the routes, controllers and views through a simple scaffold. Node.js on the other hand requires most of this to be done manually.

Create the Model and Schema

Remember that model folder we created earlier? We are going to use that folder to form our objects. Create a new file within that folder for whatever your object is going to be. In this case, I'm going to call it blobs.js. Use the plural form of the object.
Each blob is going to have a Name (string), Badge (number), DOB (date), and IsLoved (boolean). Mongoose Schema Types
  1. var mongoose = require('mongoose');  
  2. var blobSchema = new mongoose.Schema({  
  3.   name: String,
  4.   badge: Number,
  5.   dob: { type: Date, default: Date.now },
  6.   isloved: Boolean
  7. });
mongoose.model('Blob', blobSchema);
Within app.js add this to your variables at the top below our db variable we added earlier
  1. ...
  2. db = require('./model/db'),
  3. blob = require('./model/blobs'),
  4. ...
Written by Kendrick Coleman
If you found this post interesting, follow and support us.
Suggest for you: