Exploring MERN (MongoDB,ExpressJS,ReactJS,NodeJS) Stack

Rajnilari2015
Posted by in NoSql category on for Beginner level | Points: 250 | Views : 2113 red flag

This is a series for the Exploration of the MERN(MongoDB,ExpressJS,ReactJS,NodeJS) stack and in this first part we will look into mostly environment setup with a simple static record display part using REACTJS.


 Download source code for Exploring MERN (MongoDB,ExpressJS,ReactJS,NodeJS) Stack

Recommendation
Read Starting with ReactJS or React.js before this article.

Introduction

Sometime back we have looked into these four technologies in individual forms as

  1. Starting with ReactJS or React.js
  2. CRUD with NodeJS and ExpressJS
  3. Installaton guide of MongoDB on Windows 64 bit machine and

The time has reached for a fusion of all these technologies. In this series of articles, we will explore the MERN (MongoDB,ExpressJS,ReactJS,NodeJS) stack and gradually we will build a complete CRUD to demonstrate a full functional operation. 

In this first part we will look into mostly environment setup with a simple static record display part using REACTJS.

We will pick up the same example as mentioned for CRUD with NodeJS and ExpressJS as the use case for our experiment.

Environment Setup

Step 1:

We need to first install Node.js into the system.To check if NodeJS is properly installed or not, from the command prompt issue

	
C:\Users\niladri.biswas>node -v
v0.12.0

Step 2:

We also need to install the node utilities like Gulp, Bower and Nodemon in the system. For doing so, let's issue the below command

npm install -g gulp bower nodemon

Gulp is a task runner which uses Node.js to automate and enhance the workflow. It is a streaming build system that does so by using node’s streams file manipulation. This happens all in memory. In other words, Gulp is more of a build framework.

Bower is a package manager which manage components that comprises of HTML, CSS, JavaScript,frameworks, libraries, assets, utilities, fonts, image files etc. It helps to maintain the right versions of the packages we need and their dependencies. e.g.

{

  "name": "EmployeeCRUDUsingMERN",

  "description": "Example of Bower.json",

  "main": "index.js",

  "authors": [

    "RNA Team"

  ],

  "license": "ISC",

  "moduleType": [

    "node"

  ],

  "homepage": "",

  "ignore": [

    "**/.*",

    "node_modules",

    "bower_components",

    "test",

    "tests"

  ],

  "dependencies": {

    "bootstrap-css": "~3.3.4",

   "jquery": "~2.1.1"

  }

}

The example shows that, there is a dependency on bootstrap and jquery library.

Nodemon is a utility that monitors for any changes in the development source files and automatically restart the server whenever a code change happens. nodemon will watch the files in the directory and if there is a change in the files,it will automatically restart the node application.It does not look for any changes made in the source code of development. By issuing the below command we install nodemon   

npm install nodemon -g

The -g flag in the above command ensures that the node utilities (viz. Gulp, Bower and Nodemon in our case) is available globally for any project. After successful installation, we will receive a similar kind of Command Prompt as under

Step 3:

Let us now create a directory

C:\Users\niladri.biswas\Desktop\dotnetfunda>mkdir EmployeeCRUDUsingMERN

Next we need to create package.json (the file that holds various metadata relevant to the project and allows npm to identify the project as well as handle the project's dependencies) and bower.json (the manifest file for bower packages) files inside the directory EmployeeCRUDUsingMERN. For doing so, we will issue the below command (first for package.json)

C:\Users\niladri.biswas\Desktop\dotnetfunda\EmployeeCRUDUsingMERN>npm init

At this point if we open the package.json, it will look

{
  "name": "EmployeeCRUDUsingMERN",
  "version": "1.0.0",
  "description": "A CRUD for the demonstration purpose of ReactJS, ExpressJS, MongoDB and NodeJS",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "RNA Team",
  "license": "ISC"
}

And now for bower.json

C:\Users\niladri.biswas\Desktop\dotnetfunda\EmployeeCRUDUsingMERN>bower init

At this point if we open the bower.json, it will look

{
  "name": "EmployeeCRUDUsingMERN",
  "description": "A CRUD for the demonstration purpose of ReactJS, ExpressJS, MongoDB and NodeJS",
  "main": "index.js",
  "authors": [
    "RNA Team"
  ],
  "license": "ISC",
  "moduleType": [
    "node"
  ],
  "homepage": "",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ]
}

Step 4:

The next dependencies that we need are browserify,express,guid,gulp,react,react-dom,reactify,vinyl-source-stream.

browserify is a tool for compiling node-flavored commonjs modules for the browser. We write our modules in separate files, exporting external methods and properties using the module.exports and exports variables. If we require other modules, we do so by using require function. The command line for browserify  is

npm install browserify -g

Browserify uses the term entry file(s)from where it starts reading the dependency graph, goes through the graph pathand finally produces the output which is referred as bundle.

CommonJs module pattern helps to add references to various js libraries as opposed to adding script tags in individual html pages thereby prevents all the UI pages from being getting polluted.The CommonJs module pattern only allowed one module per file - it there by eliminates circular dependencies and helps in finding out the properties regarding the current module.

express is a fast, unopinionated, minimalist web framework for NodeJS.

reactify transform/transpile JSX to javascript.

vinyl-source-stream converts the readable stream from browserify into a vinyl stream which gulp expects. It is a Virtual file format that gulp expects so that it does not create a temporal file while making the transformation.

Armed with these information, let us now issue the below command

C:\Users\niladri.biswas\Desktop\dotnetfunda\EmployeeCRUDUsingMERN>npm install --save browserify reactify vinyl-source-stream gulp react react-dom express guid

We receive the below at the command prompt



At this point if we open the package.json, it will look

{
  "name": "EmployeeCRUDUsingMERN",
  "version": "1.0.0",
  "description": "A CRUD for the demonstration purpose of ReactJS, ExpressJS, MongoDB and NodeJS",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "RNA Team",
  "license": "ISC",
  "dependencies": {
    "browserify": "^12.0.1",
    "express": "^4.13.3",
    "guid": "0.0.12",
    "gulp": "^3.9.0",
    "react": "^0.14.5",
    "react-dom": "^0.14.5",
    "reactify": "^1.1.1",
    "vinyl-source-stream": "^1.1.0"
  }
}

Step 5:

Now, let us create two more folders inside root directory(which is EmployeeCRUDUsingMERN) viz app and server. Inside app folder create actions, components,dist and stores folders.

Step 6:

Next let's add the following two file .bowerrc and gulpfile.js inside the root directory(which is EmployeeCRUDUsingMERN) of the app. Open the .bowerrc and write the below code

{
    "directory":"app/lib"
}	

Create a file server.js inside the server folder

Step 7:

The next component to add is bootstrap library

C:\Users\niladri.biswas\Desktop\dotnetfunda\EmployeeCRUDUsingMERN>bower install --save bootstrap-css

At this point if we open the bower.json, it will look

{
  "name": "EmployeeCRUDUsingMERN",
  "description": "A CRUD for the demonstration purpose of ReactJS, ExpressJS, MongoDB and NodeJS",
  "main": "index.js",
  "authors": [
    "RNA Team"
  ],
  "license": "ISC",
  "moduleType": [
    "node"
  ],
  "homepage": "",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "bootstrap-css": "~3.3.4"
  }
}

Using the code

Now, let us open the server.js file inside the server folder and write the below piece of code

//add the express module
var express = require("express");

//add the path module
var path = require("path");

//create an instance of express module
var app = express();

//express.static built-in middle ware function in Express is used here for serving the static files
//like html, css, images etc. from EmployeeCRUDUsingMERN/app/dist directory
app.use(express.static(path.join(__dirname,"../app/dist")));

//run the server
  var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('RNA  Team Says: Server started and is listening at :> http://%s:%s', host, port);
});

In the beginning, we have imported the needed modules and created an instance of express module. Then we have used express.static built-in middleware function available in Express to serve the static files like html, css, images etc. from EmployeeCRUDUsingMERN/app/dist directory.And finally the app starts a server and listens on port 3000 for connection.

Next let's add index.html ,style.css and main.jsx files inside the app folder. Open the index.html and add the below content to it

<html>
    <head>   
        <title>CRUD Demo Using MongoDB,ExpressJS,ReactJS,NodeJS(MERN Stack)</title>
        <link href="bootstrap.min.css" rel="stylesheet" />
        <link href="style.css" rel="stylesheet" />
    </head>
    <body>
        <h2>Hello From RNA Team</h2>
        <h4>CRUD Demo Using MongoDB,ExpressJS,ReactJS,NodeJS(MERN Stack)</h4>
        <script src="main.js"></script>
    </body>
</html>

Now run

C:\Users\niladri.biswas\Desktop\dotnetfunda\EmployeeCRUDUsingMERN>nodemon .\server\server.js

The server will be up and running

Now browse http://localhost:3000/index.html and boom!!!

404 Error : Resource Not found

To solve this, let's open the gulpfile.js and add the below line of code

var gulp = require("gulp");
var browserify = require("browserify");
var reactify = require("reactify");
var source = require("vinyl-source-stream");

//Task# 1
//Purpose: This task transpiles/transform the .jsx code to javascript code on the fly by using reactify. Once done, then by using vinyl-source-stream
//         it creates main.js file on the fly inside the dist directory with transformed javascript code in it.
gulp.task("bundle", function () {
    return browserify({
        entries: "./app/main.jsx",
        debug: true
    }).transform(reactify)
        .bundle()
        .pipe(source("main.js"))
        .pipe(gulp.dest("app/dist"))
});


//Task# 2
//Purpose: Copies index.html, bootstrap.min.css and style.css files to ./app/dist folder.
gulp.task("copy", ["bundle"], function () {
    return gulp.src(["app/index.html","app/lib/bootstrap-css/css/bootstrap.min.css","app/style.css"])
        .pipe(gulp.dest("app/dist"));
});

//Confirms that the task is over. It should be the default one
gulp.task("default",["copy"],function(){
   console.log("RNA  Team Says: Gulp completed it's task"); 
});

Code Explanation

The gulpfile.js serves two important tasks. First, it transpiles/transform the .jsx code to javascript code on the fly by using reactify. Once done, then by using vinyl-source-stream it creates main.js file on the fly inside the dist directory with transformed javascript code in it. The second one is that, it copies index.html, bootstrap.min.css and style.css files to ./app/dist folder.

Next open another Command Prompt window and type the below command

C:\Users\niladri.biswas\Desktop\dotnetfunda\EmployeeCRUDUsingMERN>gulp

Let us now refresh the page in the browser

An important point to note here that, as and when we make the changes, the nodemon takes care of that without further restarting the server (rather that's it's behaviour)

Now if we open the dist folder under the app folder, we will find

The REACT In Action

Now let's include two files EmployeeView.jsx and EmployeeDetails.jsx under the components folder and add the below line of code(s)

EmployeeView.jsx
------------------
var React = require("react");
var EmployeeDetail = require("./EmployeeDetails.jsx")

module.exports = React.createClass({
   render:function(){
       return(                     
                  <div>
                      {
                          this.props.employees.map(function(s,index){
                              return(
                               
                                  <EmployeeDetail info={s} key={"employee"+index} />
                              )         
                          })
                      }
                  </div>
           
            )}//end render function 
    });//end createClass


EmployeeDetails.jsx
--------------------
var React = require("react");

module.exports = React.createClass({
    render:function(){
        return  (
                    <div className="panel panel-default">
                        <div className="panel-heading">
                            {this.props.info.EmployeeName}
                        </div>
                        <div className="panel-body">                            
                            <table border="2">                    
                                <tr>
                                    <td>EmployeeID: <b>{this.props.info.EmployeeID}</b>  </td>                                   
                                    <td> Salary: <b>{this.props.info.Salary}</b>  </td>
                                    <td> Address: <b>{this.props.info.Address}</b></td>
                                </tr>
                            </table> 
                        </div>
                    </div>
                )
    }//end render function
}) //end createClass

Also let's add the below code piece in main.jsx which is under the app folder

main.jsx
----------
var React = require("react");
var ReactDOM = require("react-dom");
var EmployeesList = require("./components/EmployeeView.jsx");

var employeesRepository =	
[
{EmployeeID :1,EmployeeName : "RNA Team",Salary : "270000",Address : "Bangalore"},
{EmployeeID :2,EmployeeName : "Rajlaxmi Biswas",Salary : "100000",Address : "Bangalore"},
{EmployeeID :3,EmployeeName : "Niladri Biswas",Salary : "90000",Address : "Bangalore"},
{EmployeeID :4,EmployeeName : "Arina Biswas",Salary : "80000",Address : "Bangalore"}
				
];			   
                
function render(){
    ReactDOM.render(, document.getElementById("container"));    
}
render();

We have equally modified our index.html a bit which is as under

<html>
	<head>
	    <meta charset="UTF-8">
	    <title>CRUD Demo Using MERN Stack</title>
	    <link href="bootstrap.min.css" rel="stylesheet" />	   
	</head>

	<body>
		<center>
	   		<h2>Hello From RNA Team</h2>
	   		<h4><u>CRUD Demo Using MERN Stack</u></h4>  
	   		<h4><font color="blue"><b><u>Employee Details</u></b></font></h4>		     	
		    <div id="container" class="container"></div>
	    </center>
	    <script src="main.js"></script>
	</body>
</html>

Now run the gulp command again

C:\Users\niladri.biswas\Desktop\dotnetfunda\EmployeeCRUDUsingMERN>gulp

and in the browser

References

  1. GETTING STARTED WITH GULP
  2. An Introduction to Gulp.js
  3. Bower
  4. reactify
  5. browserify

Conclusion

Hope everyone enjoyed the journey with the part 1. In the next part, we will learn about the FLUX Architecture. Zipped file attached. Thanks for reading.

Recommendation
Read CRUD with NodeJS and ExpressJS after this article.
Page copy protected against web site content infringement by Copyscape

About the Author

Rajnilari2015
Full Name: Niladri Biswas (RNA Team)
Member Level: Platinum
Member Status: Member,Microsoft_MVP,MVP
Member Since: 3/17/2015 2:41:06 AM
Country: India
-- Thanks & Regards, RNA Team


Login to vote for this post.

Comments or Responses

Login to post response

Comment using Facebook(Author doesn't get notification)