In the previous chapters, we have learnt about React routing, the integration of the Facebook API, and how we can configure and handle app URLs. We have also learnt how we can register our component in the DOM according to the URL.
In this chapter, we will build our existing application with Node.js. I'm not going to show you how to connect with the server and build the server-side aspect here, as that's outside the scope of this book. However, it is included in the code files that accompany the book. Here's what we'll be covering in this chapter:
So far our application is entirely based on the frontend and also it's not modularized. Of course, this means our application code looks messy. We are also using an unpackaging file for every dependency library of React and the browser has to go and fetch each JavaScript file and compile it.
We'll no longer need to manually concatenate and minify, but instead we can have a setup watching our files for changes and automatically make them, such as webpack
and webpack-hot-middleware
.
Let's continue to make changes in our project and it would be tedious to continually repeat the process.
First we need to download and install Node.js. If you have already installed and configured Node, feel free to skip this section. We can download Node.js from http://nodejs.org and follow the instructions mentioned as follows:
The installer wizard will ask for your choice of features to be installed, and you can select the one you want. Usually, we select the default installation:
Once the system is restarted, we can check whether Node.js was set up properly or not.
Open the command prompt and run the following command:
node --version // will result something like v0.12.10
You should be able to see version information, which ensures that the installation was successful.
First we need to create a package.json
file for our project, which includes the project information and dependencies of the npm modules. npm is very useful for JavaScript developers to create and share the reusable code that they have created to build an application and solve particular problems while developing it.
Now, open the command prompt/console and navigate to the directory you have created. Run the following command:
Npm init
This command will initialize our app and ask several questions to create a JSON file named package.json
. The utility will ask questions about the project name, description, entry point, version, author name, dependencies, license information, and so on. Once the command is executed, it will generate a package.json
file in the root directory of your project.
{ "name": "react-node", "version": "1.0.0", "description": "ReactJS Project with Nodejs", "scripts": { "start": "node server.js", "lint": "eslint src" }, "author": "Harmeet Singh <[email protected]>", "license": "MIT", "bugs": { "url": "" },
In the preceding code, you can see the name
of the application, the entry point of your application (start
), the version
of your application, and the description
of your application.
Now we need to install some Node modules, which are going to help us with building a React application with Node. We will use Babel, React, React-DOM, Router, Express, and so on.
Following is the command for installing the modules through npm
:
npm install <package name> --save
When we run the aforementioned command with the <package name>
, it will install the package in your project folder/node_modules
and save the package name/version
in your package.json
which will help us to install all the project dependencies and update the modules in any system.
If you already have the package.json
file with the project dependencies then you only need to run the following command:
npm install
And to update we need to run the following command:
npm update
Here is a list of modules that have dependencies in our application:
"devDependencies": { "babel-core": "^6.0.20", "babel-eslint": "^4.1.3", "babel-loader": "^6.0.1", "babel-preset-es2015": "^6.0.15", "babel-preset-react": "^6.0.15", "babel-preset-stage-0": "^6.0.15", "body-parser": "^1.15.2", "eslint": "^1.10.3", "eslint-plugin-react": "^3.6.2", "express": "^4.13.4", "react-hot-loader": "^1.3.0", "webpack": "^1.12.2", "webpack-dev-middleware": "^1.6.1", "webpack-hot-middleware": "^2.10.0" }, "dependencies": { "mongodb": "^2.2.11", "mongoose": "^4.6.8", "react": "^0.14.6", "react-dom": "^0.14.6", "react-router": "^1.0.0-rc1", "style-loader": "^0.13.1", "url-loader": "^0.5.7", "css-loader": "^0.26.0",a "file-loader": "^0.9.0" }
In the preceding dependencies
list there may be some modules you have not heard of or are new to you. OK, let me explain:
mongoose
and mongodb
: These work as a middleware in an application or MongoDB. Installing MongoDB and mongoose is optional for you as we are not using them in our application. I have just added them for your reference.nodemon
: During development in a Node.js app, nodemon
will watch the files in the directory and if any files change, it will automatically restart your node application.react-hot-loader
: This is the most commonly used module in web development for live code editing and project reloading. The react-hot-loader
itself has some dependency on other modules:webpack
webpack-hot-middleware
webpack-dev-middleware
webpack-hot-middleware
: This allows you to add hot reloading into an existing server without webpack-dev-server
. It connects a browser client to a webpack server to receive updates and subscribes to changes from the server. It then executes those changes using webpack's Hot Module Replacement (HMR) API.webpack-dev-middleware
: This is a webpack wrapper and serves the file that is emitted from webpack over a connected server. It has the following advantages while developing:
style-loader
, url-loader
, css-loader
, and file-loader
help to load static path, CSS, and files.
For example: import '../vendor/css/bootstrap.min.css'
, which includes the font URL and images path.
After setting up the package.json
file, we have our HTML markup as shown in the following code, named index.html
:
<!doctype html> <html> <head> <title>React Application - EIS</title> <script src="//ajax.googleapis.com/ajax/libs/jquery/ 1.11.1/jquery.min.js"></script> </head> <body> <div id='root'> </div> <script src="/static/bundle.js"></script> </body> </html>
Now we need to create a server in server.js
to run our application:
var path = require('path'); var webpack = require('webpack'); var express = require('express'); var config = require('./webpack.config'); var app = express(); var compiler = webpack(config); app.use(require('webpack-dev-middleware')(compiler, { publicPath: config.output.publicPath })); app.use(require('webpack-hot-middleware')(compiler));
In the preceding code, we are configuring the webpack
in our application. It connects to the server and receives the update notification to rebuild the client bundle:
app.get('*', function(req, res) { res.sendFile(path.join(__dirname, 'index.html')); }); app.listen(3000, function(err) { if (err) { return console.error(err); } console.log('Listening at http://localhost:3000/'); })
In the preceding code, we are sending an HTML file and starting the server. You can change the port number as required.
Now let's take a look at webpack.config.js
, which we just included at the top of our server.js
file.
module.exports = { devtool: 'cheap-module-eval-source-map', entry: [ 'webpack-hot-middleware/client', './src/index' ], output: { path: path.join(__dirname, 'dist'), filename: 'bundle.js', publicPath: '/static/' }, plugins: [ new webpack.HotModuleReplacementPlugin() ],
In the preceding code, we are setting up the webpack-hot-middleware
plugin and adding the entry point of our script to compile and run:
module: { loaders: [{ test: /.js$/, loaders: ['react-hot', 'babel'], include: path.join(__dirname, 'src') }, { test: /.css$/, loader: 'style!css', exclude: /node_modules/ }, { test: /.(woff|woff2|ttf|svg)$/, loader: 'url?limit=100000', exclude: /node_modules/ }, { test: /.(eot|png)$/, loader: 'file', exclude: /node_modules/ } ] } };
Here, we are loading the modules according to the matched files in our application.
We also need to configure Babel, which includes the ECMAScript version and eslint
for adding some rules, plugin information, and so on.
The .babelrc
file includes:
{ "presets": ["es2015", "stage-0", "react"] }
The .eslintrc
file includes:
{ "ecmaFeatures": { "jsx": true, "modules": true }, "env": { "browser": true, "node": true }, "parser": "babel-eslint", "rules": { "quotes": [2, "single"], "strict": [2, "never"], "react/jsx-uses-react": 2, "react/jsx-uses-vars": 2, "react/react-in-jsx-scope": 2 }, "plugins": [ "react" ] }
Observe the following screenshot:
The preceding screenshot shows our folder structure for the root directory. In the src
directory, we have all the scripts and, in the vendor folder, we have the Bootstrap fonts and CSS.