JS React Material Express: Setting Up a Project Using Npm, Webpack, Babel

react-logoThis is the simplest example to build a webapp using ReactJS, MaterialUI and ExpressJS in a project with Npm, Webpack, Babel.

A lot of these tools are not required to use React. But using ES6, JSX is more productive.

Stack

  • NodeJs – A JavaScript runtime built on Chrome’s V8 JavaScript engine.
  • Npm – The package manager for JavaScript and the world’s largest software registry.
  • ReactJS – The state based framework for your Views
  • ExpressJS – The node framework to serve your views to the world when they hit the server at example.com or example.com/awesome.html
  • MaterialUI – A Set of React Components that ImplementGoogle’s Material Design
  • Webpack – The module binder which takes all your JS files from different directories and compiles them into a single app.bundle.js (you can change the filename of course) so you can include it in a HTML page
  • Babel – The compiler to compile your JS files with es6, es7, JSX syntax to regular javascript

Steps

  1. Init NodeJs, Project
  2. Add Express
  3. Add React
  4. Add Material

1. Init NodeJs, Project

1.1 Install NodeJs

Go to NodeJs website and download the stable version (LTS).

https://nodejs.org/en/

ScreenShot008.png

1.2 Create Project

Create a new folder ‘YOUR_PROJECT_NAME’ and initialize it with npm.

mkdir YOUR_PROJECT_NAME
cd YOUR_PROJECT_NAME
npm init

Answer all the questions about your project.

ScreenShot003

ScreenShot006.png

ScreenShot004.png

1.3. Install WebPack

npm install
npm install webpack -g

ScreenShot005.png


2. Add Express

Add Express to your build (package.json).

"dependencies": {
 "express": "4.13.3",
 "compression": "1.6.0"
 },
 "devDependencies": {
 }

 ScreenShot009.png

Add then Implement Express Server (server.js).

ScreenShot010.png

It’s a simple example with a REST API that provide server’s status.

// Module dependencies.
var express = require('express'),
 compression = require('compression');

// Configuration
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(compression());
var http = require('http').Server(app);

// Routes
app.use('/', express.static('./public'));

// REST
app.get('/api/status', function (req, res) {
 var status = "ONLINE (v1.0.0)";
 res.send(status);
});

// Start server
var server = http.listen(app.get('port'), function(){
 var host = server.address().address;
 var port = server.address().port;
 console.log('Example app listening at http://%s:%s', host, port);
});

2.3 Test it

Build

npm install

ScreenShot011.png

Start

npm start

ScreenShot012.png

Test

http://localhost:5000/api/status

ScreenShot002.png


3. Add React

3.1. Config React

ScreenShot003.png

package.json

"scripts": {
 "start": "node server.js",
 "test": "echo \"Error: no test specified\" && exit 1"
 },

"dependencies": {

  "express": "4.13.3",
  "compression": "1.6.0",

  "react": "15.4.2",
  "react-dom": "15.4.2",

  "babel-core": "6.24.1",
 },
 "devDependencies": {

   "babel-loader": "6.4.0",
   "babel-preset-es2015":  "6.24.1",
   "babel-preset-react":   "6.24.1",
   "babel-preset-stage-1": "6.24.1",

   "webpack": "2.6.1",
   "webpack-dev-server": "2.4.5",

"html-webpack-plugin": "2.28.0"
 }

webpack.config.js

'use strict';

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = [
{
entry: './views/index.jsx',
output: {
path: __dirname + '/public/',
filename: '[name].js',
publicPath: '/'
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({
template: 'views/index.tpl.html',
inject: 'body',
filename: 'index.html'
})
],
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
"presets": ["react", "es2015"]
}
}]
}
}
];

3.2. Implement React

ScreenShot002.png

views/index.tpl.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>JS React Material Express</title>
    <meta name="description" content="Setting Up a Project Using Npm, Webpack, Babel">
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>
<div id="app"></div>
</body>
</html>

views/index.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import App from './app.jsx';

ReactDOM.render(
	<App />,
	document.getElementById('app'));

views/app.jsx

import React from 'react';

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {test: 'foo'};
  }
  render() {
    return (
<div>
        Hello World!</div>
);
  }
}

3.3. Test React

npm install
webpack
node server

ScreenShot009.png

ScreenShot010.png

ScreenShot011

ScreenShot002.png

4. Add Material

4.1. Config Material

package.json

  "dependencies": {
    ...
    "material-ui": "0.18.1",
    "react-tap-event-plugin": "2.0.1"
  },

4.2. Implement Material

views/index.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import App from './app.jsx';

import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin();

ReactDOM.render(
  <MuiThemeProvider>
	<App />
  </MuiThemeProvider>,
	document.getElementById('app'));

views/app.jsx

import React from 'react';
import {Card, CardActions, CardHeader, CardMedia, CardTitle, CardText} from 'material-ui/Card';
import FlatButton from 'material-ui/FlatButton';

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {test: 'foo'};
  }
  render() {
    return (
  <Card>
    <CardHeader       title="Hello Title"       subtitle="Subtitle"       actAsExpander={true}       showExpandableButton={true}     />
    <CardActions>
      <FlatButton label="OK" />
      <FlatButton label="CANCEL" />
    </CardActions>
    <CardText expandable={true}>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit.
      Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi.
      Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque.
      Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio.
    </CardText>
  </Card>
    );
  }
}

4.3. Test Material

ScreenShot003.png

ScreenShot004.png


Code

Here is the final project content.

  • views
    • app.jsx
    • index.jsx
    • index.tpl.html
  • package.json
  • server.js
  • webpack.config.js

package.json

{
  "name": "20170529-js-react-material-express-setting_up_a_project",
  "version": "1.0.0",
  "description": "JS React Material Express: Setting Up a Project Using Npm, Webpack, Babel",
  "author": "Damien FREMONT",

  "main": "server.js",
  "scripts": {
    "start": "node server.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

  "dependencies": {

    "express": "4.13.3",
    "compression": "1.6.0",

    "react": "15.4.2",
    "react-dom": "15.4.2",

    "babel-core": "6.24.1",

    "material-ui": "0.18.1",
    "react-tap-event-plugin": "2.0.1"
  },
  "devDependencies": {

    "babel-loader": "6.4.0",
    "babel-preset-es2015":  "6.24.1",
    "babel-preset-react":   "6.24.1",
    "babel-preset-stage-1": "6.24.1",

    "webpack": "2.6.1",
    "webpack-dev-server": "2.4.5",

    "html-webpack-plugin": "2.28.0"
  }
}

webpack.config.js

'use strict';

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = [
{
  entry: './views/index.jsx',
  output: {
    path: __dirname + '/public/',
    filename: '[name].js',
    publicPath: '/'
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({
      template: 'views/index.tpl.html',
      inject: 'body',
      filename: 'index.html'
    })
  ],
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel-loader',
      query: {
        "presets": ["react", "es2015"]
      }
    }]
  }
}
];

server.js

// Module dependencies.
var express = require('express'),
 compression = require('compression');

// Configuration
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(compression());
var http = require('http').Server(app);

// VIEW Routes
app.use('/', express.static('./public'));

// REST
app.get('/api/status', function (req, res) {
  var status = "ONLINE (v1.0.0)";
  res.send(status);
});

// Start server
var server = http.listen(app.get('port'), function(){
  var host = server.address().address;
  var port = server.address().port;
  console.log('Example app listening at http://%s:%s', host, port);
});

views/index.tpl.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>JS React Material Express</title>
    <meta name="description" content="Setting Up a Project Using Npm, Webpack, Babel">
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>
<div id="app"></div>
</body>
</html>

views/index.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import App from './app.jsx';

import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin();

ReactDOM.render(
  <MuiThemeProvider>
	<App />
  </MuiThemeProvider>,
	document.getElementById('app'));

views/app.jsx

import React from 'react';
import {Card, CardActions, CardHeader, CardMedia, CardTitle, CardText} from 'material-ui/Card';
import FlatButton from 'material-ui/FlatButton';

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {test: 'foo'};
  }
  render() {
    return (
  <Card>
    <CardHeader       title="Hello Title"       subtitle="Subtitle"       actAsExpander={true}       showExpandableButton={true}     />
    <CardActions>
      <FlatButton label="OK" />
      <FlatButton label="CANCEL" />
    </CardActions>
    <CardText expandable={true}>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit.
      Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi.
      Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque.
      Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio.
    </CardText>
  </Card>
    );
  }
}

Source

https://github.com/DamienFremont/blog/tree/master/20170529-js-react-material-express-setting_up_a_project

Reference

https://www.python.org/downloads/

https://facebook.github.io/react/

http://www.material-ui.com/#/

https://webpack.js.org/guides/installation/#local-installation

https://github.com/christianalfoni/webpack-express-boilerplate

https://github.com/tahnik/react-express-webpack-babel

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s