Today is May 20, 2016. I’ve been messing around with Node.js and Express for the web framework, MongoDB for the database, Bower for dependencies, and Gulp for automating tasks. This post will be a guide step-by-step on how to setup Node, Express, Mongo, Bower, and Gulp as of May 2016. I am using a Windows 10 machine for the installation and setup. Commands will be slightly different for Macs and Linux users. We will be making a log in, sign up, and blog post page with users.
Part 1 – Setup
If you only want to browse the code, all source code will be available on this Github link.
Download and Install Node.js
We will install Node.js first. Node.js’s website will automatically detect what operating system you have. Run the setup and get Node.js installed.
Download and Install MongoDB
We will download and install MongoDB. I chose the community server, Windows Server 2008 R2 and later. Run the setup and get MongoDB installed.
OPTIONAL: Cygwin64
I’m using Cygwin64 to obtain UNIX commands on Windows 10. I need to add cygwin64\bin to the System Variable, Path, so that Node.js command prompt can use UNIX binaries. Open the file explorer. Right click This PC and click Properties. Click Advanced System Settings on the left. Go to the Advanced tab. Click Environment Variables. Underneath System Variables, click Path. Click New. Add the path to cygwin64\bin where you installed Cygwin64. For me, I added C:\Users\huyle\Desktop\cygwin64\bin
.
Install the Node.js express generator
We open the Node.js command prompt by searching it with Windows search. Install express-generator, bower, and gulp globally.
npm install -g express-generator --ejs npm install -g bower gulp
Make a folder where you want to keep your project and change directory into the folder.
mkdir node-express-mongo-bower-gulp-template cd node-express-mongo-bower-gulp-template
Now, we will use the express-generator to generate a nice express template. If there are files inside the folder, type y and enter.
express .
By default, express-generator uses jade as the template language, but I’d rather use ejs because ejs is much more similar to html. Remove the jade files inside the views/
folder.
Change jade to ejs for the template engine. Open the app.js file.
Originally, app.js
is:
1 2 3 | // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); |
We make a slight change to those two lines to:
1 2 3 | // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); |
package.json
contains Node.js dependencies. We want to delete the line that contains the jade dependency. Originally, package.json
is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | { "name": "node-express-mongo-bower-gulp-template", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www" }, "dependencies": { "body-parser": "~1.13.2", "cookie-parser": "~1.3.5", "debug": "~2.2.0", "express": "~4.13.1", "jade": "~1.11.0", "morgan": "~1.6.1", "serve-favicon": "~2.3.0" } } |
We delete the jade dependency and change the file to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | { "name": "node-express-mongo-bower-gulp-template", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www" }, "dependencies": { "body-parser": "~1.13.2", "cookie-parser": "~1.3.5", "debug": "~2.2.0", "ejs": "^2.4.1", "morgan": "~1.6.1", "serve-favicon": "~2.3.0" } } |
We install ejs with the Node.js command prompt.
npm install --save ejs
Because we removed the jade files, we may be missing .ejs files inside the views folder. If you do not have any .ejs files inside the views/
folder, you can grab index.ejs and error.ejs and save them to the views/ folder.
We also have to install the rest of the dependencies in package.json
. npm looks for a package.json
when using npm install
. Type:
npm install
All npm packages are stored in a folder called node_modules/
.
Bower
Now, we want to setup bower. First, we initialize bower:
bower init
There will be several prompts, which you can leave by default. bower init
creates a bower.json
file. This json file works in the same way as package.json
. Bower is used for styling and javascript dependencies.
bower install bootstrap-sass fontawesome --save
All bower dependencies are saved in a folder called bower_components/
.
Gulp
We have to get some dependencies for Gulp, which will make our lives easier. --save-dev
tells package.json
that these packages are only for development since you will only need gulp’s automation for development.
npm install gulp gulp-sass gulp-notify gulp-bower gulp-autoprefixer --save-dev
Sass
Sass is a CSS extension language that provides extra functionality like nesting and importing. We need to install Sass through gems. To use gems, we need to install the programming language called Ruby by visiting the Ruby installer website. I downloaded rubyinstaller-2.3.0-x64.exe. Make sure that you check Add Ruby executables to your PATH.
After installing Ruby, you will also need the Ruby Dev Kit. On the same page, scroll down and download the DevKit. I downloaded DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe.
Create a folder somewhere convenient like your Desktop called ruby-dev
, and use the DevKit .exe to extract to that folder. Open the folder with File Explorer. Hold Shift and Right Click white space
on the folder. Click Open Command Window Here
. A command prompt should open. To check if you installed Ruby properly, type:
ruby -v
Now, we will install the gem command. On the same terminal:
ruby dk.rb init ruby dk.rb install
We can now install sass:
gem install sass
After installing sass, inside the public/
folder of our project, we will make a new folder called sass/
.
Make a file called style.scss
inside the sass/
folder, and write:
1 2 | @import "bootstrap"; @import "font-awesome"; |
Now, create a file called gulpfile.js
on the root of the project folder, node-express-mongo-bower-gulp-template/
. I’ve created a gulpfile.js
that installs bower dependencies listed in bower.json
, moves font-awesome fonts in the public folder, and converts sass to css.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | // Basic Gulp File var gulp = require('gulp'); var sass = require('gulp-sass'); var autoprefix = require('gulp-autoprefixer'); var notify = require("gulp-notify"); var bower = require('gulp-bower'); var config = { bootstrapDir: './bower_components/bootstrap-sass', fontawesomeDir: './bower_components/font-awesome', publicDir: './public', bowerDir: './bower_components' } gulp.task('bower', function() { return bower() .pipe(gulp.dest(config.bowerDir)) }); gulp.task('fonts', function() { return gulp.src(config.bowerDir + '/font-awesome/fonts/**.*') .pipe(gulp.dest('./public/fonts')); }); gulp.task('css', function() { return gulp.src('./public/sass/style.scss') .pipe(sass({ includePaths: [config.bootstrapDir + '/assets/stylesheets', config.fontawesomeDir + '/scss'], })) .pipe(gulp.dest(config.publicDir + '/stylesheets')); }); // Watch task gulp.task('watch',function() { gulp.watch('./public/sass/**/*.scss', ['css']); }); gulp.task('default', ['bower', 'fonts', 'css']); |
To use gulp, run the following in the command prompt:
gulp
You can also use the following command to have gulp automatically convert sass to css whenever a sass file inside /public/sass
changes.
gulp watch
To start your Node Express project, open another Node.js command prompt:
npm start
Visit http://localhost:3000 to see your site. To stop the Node Express server, on the terminal where you used the npm start command, press CTRL- C
.
Part 2 – MongoDB Users
We will be dealing with a lot more MongoDB for part 2 since we didn’t get a chance to touch on it in part 1. First, we need to add MongoDB to our Environment Path.
Open one new command prompt or terminal inside the project folder. Make a directory called data/
that will be the location of our MongoDB data files.
cd node-express-mongo-bower-gulp-template mkdir data/
We can start the Mongo server to save data to the data/
folder.
mongod --dbpath data/
If successful, you should see something like this. Mongo server has started up.
2016-05-23T20:36:59.265+0100 I NETWORK [HostnameCanonicalizationWorker] Starting hostname canonicalization worker 2016-05-23T20:36:59.265+0100 I FTDC [initandlisten] Initializing full-time diagnostic data capture with directory 'data/diagnostic.data' 2016-05-23T20:36:59.279+0100 I NETWORK [initandlisten] waiting for connections on port 27017
On a second command prompt window, you can start the mongo console.
mongo
MongoDB shell version: 3.2.6 connecting to: test
By default, mongo
selects test as the default database. We will use the following command to use a new database called nodetest
. You can call nodetest anything that you want.
use nodetest
On a third terminal, we will install a few more npm packages. Mongoose provides a model system for MongoDB so that we can easily tell apart one data type from the next. Passport and passport-local are used for authentication.
npm install mongodb mongoose passport passport-local express-session connect-flash bcrypt-nodejs --save
Adding a lot of new files
There are a lot of new files that we’re adding, and I won’t get a chance to explain everything. Please check out the source code on Github.
First thing that we’ll do is configure Mongo. We create a db.js
file inside the root of the folder, node-express-mongo-bower-gulp-template
. Since the name of our database is called nodetest, we use nodetest in our /db.js
file.
1 2 3 | module.exports = { 'url' : 'mongodb://localhost/nodetest' } |
We need to make sure that our /app.js
file uses Mongo and Mongoose. Add the following lines to /app.js
.
1 2 3 | var dbConfig = require('./db.js'); var mongoose = require('mongoose'); mongoose.connect(dbConfig.url); |
Since we installed passport, we also have to add the following to /app.js for authentication. We will also use connect-flash to send messages between requests. Make sure that these lines are after var app = express();
1 2 3 4 5 6 7 8 9 10 11 12 | var passport = require('passport'); var expressSession = require('express-session'); app.use(expressSession({secret: 'secretKey', resave: true, saveUninitialized: true})); app.use(passport.initialize()); app.use(passport.session()); var flash = require('connect-flash'); app.use(flash()); var initPassport = require('./passport/init'); |
The template that we are using a route called users that we want to change. Originally, on /app.js
, there are are these couple of lines:
1 2 3 4 5 | var routes = require('./routes/index'); var users = require('./routes/users'); app.use('/', routes); app.use('/users', users); |
We will change these lines to:
1 2 3 4 5 6 7 | var routes = require('./routes/index'); //var users = require('./routes/users'); var blogpost = require('./routes/blogpost'); app.use('/', routes); //app.use('/users', users); app.use('/blogpost', blogpost); |
See the full /app.js
file here:
Now, we’ll create a new folder called models. Inside the models folder, create a file called user.js
. /models/user.js
will contain our Mongoose model to define what User information we want a User to have.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var mongoose = require('mongoose'); var Schema = mongoose.Schema; var userSchema = new Schema({ username: String, password: String, email: String, firstName: String, lastName: String }); var User = mongoose.model('User', userSchema); module.exports = User; |
With the User model created, we need to configure passport for authentication. We create a new folder called passport/
inside the root folder, node-express-mongo-bower-gulp-template/
.
There are 3 files that we create for passport. Credit to tutsplus and their Authenticating Node.js Applications With Passport for most of the passport code. Save these 3 files in /passport
folder for authentication.
/passport/init.js
/passport/login.js
/passport/signup.js
After copying those files to passport, authentication and sessions will be working for login and signing up. Now, we will create blog post functionality. We create a new model inside the models/
folder called /models/blogpost.js
.
1 2 3 4 5 6 7 8 9 10 11 12 | var mongoose = require('mongoose'); var Schema = mongoose.Schema; var blogPostSchema = new Schema({ userId: String, title: String, post: String }); var BlogPost = mongoose.model('BlogPost', blogPostSchema); module.exports = BlogPost; |
On to the routes. I removed the template’s /routes/users.js
route. I added a new route called /routes/blogpost.js
inside the /routes
folder. And I changed many lines for /routes/index.js
. I left comments for every route inside these two files to explain what each function does. You can see the updates here:
/routes/index.js
/routes/blogpost.js
I created many new views to handle the appearance of the login, sign up, home, and blog post pages. These new .ejs files belong inside the /views
folder.
/views/index.ejs
/views/signup.ejs
/views/home.ejs
/views/post.ejs
I created a folder for controllers that manipulate the models. The routes then trigger a file in controllers for any functionality related to a model. For instance, /routes/blogpost.js
route uses /controllers/BlogPostController.js
, which then uses the /models/blogpost.js
model, to add users’ posts and lists all posts in the database.
/controllers/BlogPostController.js
I added a new .gitignore that ignores the /bower_components
, /node_modules
, /data
folders, and other files because you are not supposed to add these bower dependencies and npm packages during development onto Github.
Other files that may be different:
Local running
You can also clone the Github repo. If you clone the Github repo:
git clone https://github.com/huyle333/node-express-mongo-bower-gulp-template
We go into the directory and install npm and bower dependencies.
cd node-express-mongo-bower-gulp-template npm install && bower install && gulp
Now that we have all the files, to develop on this template locally, you should have 5 terminals/tabs open inside the project folder.
- 1st terminal:
mongod --dbpath data/
- 2nd terminal:
mongo
- 3rd terminal:
gulp watch
- 4th terminal:
npm start
- 5th terminal: Extra terminal for miscellaneous commands
Visit http://localhost:3000 to visit the log-in page of the template. As always, leave any comments on questions and look at the Github source code for updates.
Using mongo console
After starting the mongodb database with mongod --dbpath data/
, you can start the mongo console with a second terminal running mongo
. All commands are available at the official mongo shell documentation.
To show all the collections or models:
show collections
blogposts users
To show the contents of a collection:
db.users.find()
To remove all the contents of a collection:
db.users.remove({})