Valerii Iatsko

Full Stack Developer

Hi! My name is Valerii Iatsko.

I'm a Full Stack Developer and the author of this blog.

→ Follow on Twitter

React for Beginners - Episode 1 - Setting up repository, babel, express web server & webpack

I know, there’s a lot of articles in the network and boilerplates which are aiming to help you setting up the stuff to start your first React application. But what I’m worrying about is that they are still too hard, over-engineered and are leaving more questions than answers.

In these series, I assume that you know JavaScript and that you understand ES6 syntax (still, I’ll try to explain hard parts of syntax here).

In the React for Beginners cycle, we’ll create a full-stack application with authorization and admin panel using React/Redux on the frontend and nodejs on the backend. I’ll assume you already have nodejs, npm and git installed.

-> Most of the stuff here came up after I invested some time investigating https://github.com/erikras/react-redux-universal-hot-example works and how to build isomorphic app using the same approach step-by-step.

GitHub

First of all, we’ll work on our project on the GitHub. Go and create an account there and start creating a new repository.

Creating a new GitHub repository

Cool! Now, let’s clone it! To do it, go to your repository page and copy repository url:

GitHub repository

Now, let’s “git clone” it. Open the terminal and enter commands (sure you can skip creating projects directory, and your repository url should be a bit different :P):

mkdir ~/projects
cd ~/projects
git clone https://github.com/viatsko/react-for-beginners

Creating npm’s package.json

Now, let’s create an npm’s package.json file there to keep track of our future dependencies and run-scripts of our project:

cd ~/projects/react-for-beginners
npm init

You can just hit “Enter” for every question asked or enter whatever you find fitting your project (regarding keywords, name, version, license, link to repository or author):

npm init

If you’ve done everything correctly, your project tree will look like something like this https://github.com/viatsko/react-for-beginners/tree/434417d3a07b1e460e725d535e347eeec8a43f64 (I’ll publish project tree step-by-step for you to check whether your actions were correct or not).

Babel

Nowadays, most of the projects and code written for modern javascript stack are written in ES6, Babel provides an ability to use ES6 in environments which are not supporting it in full as well as it’s providing plugin system which allows to include custom transformers such as jsx transformer for React.

Let’s set Babel up for our project!

npm install babel-plugin-transform-class-properties babel-plugin-transform-runtime \
            babel-polyfill babel-preset-es2015 babel-preset-react babel-preset-stage-0 \
            babel-register --save

What are all of these for?

  • babel-register allows you to use babel in nodejs
  • babel-polyfill emulates full ES6 environment (includes core.js)
  • babel-preset-es2015, babel-preset-stage-0, babel-preset-react are presets to enable most of the ES6 features as well as some needed for react, and jsx.
  • babel-plugin-transform-runtime allows using async/await operators (I’ll explain what are they for and how to use them later — we’ll use them a lot!)
  • babel-plugin-transform-class-properties is for using static variables inside ES6 classes (it’s not a very common practice, but I find this syntax a little bit more natural for people to understand, I’ll explain this later)

We’ll also need to create .babelrc file inside the project’s directory:

{
  "presets": [
    "es2015",
    "stage-0",
    "react"
  ],
  "plugins": [
    "transform-runtime",
    "transform-class-properties"
  ]
}

This enables all the stuff we installed.

Your directory tree will look like this https://github.com/viatsko/react-for-beginners/tree/6f6148130a919ddcef6fe8c0630a65d3aeddddac (plus node_modules directory which I’ve been excluded from the repository).

Express

Express is the most popular web server used in nodejs world. Let’s add it to our project!

First, let’s install it as the dependency:

npm install express --save

Now, we’ll need to create two files — server.js and server.babel.js. server.js will be used to initialize babel’s require hook and then will run server.babel.js.

Here’s server.js:

require('babel-register');

require('./server.babel');

We’ll use express only to host static files in the first part. Here’s the server.babel.js:

import express from 'express';

const app = express();

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

app.listen(process.env.PORT || 3000);

If you want to understand express API deeper, here’s their official API documentation. I’ll only explain here the line process.env.PORT || 3000, which means that if we’ll run application with environment variable PORT set, it will use the port declared by it, otherwise it will use port 3000. In one of the next parts of the tutorial, I’ll explain deployment process to Heroku, which is setting PORT env variable to point application where to bind on.

Now, let’s start the application using command:

node server

If everything’s ok, you can now visit http://localhost:3000/ in browser and see “Cannot GET /” message:

success

This means that everything is working fine :)

Here’s our checkpoint https://github.com/viatsko/react-for-beginners/tree/f130535874df519bc73cbefdffa208c9616855be

Webpack

In the previous chapter we created a simple server using express to host static files, now let’s create a static file called public/index.html:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Hello, world</title>
</head>
<body>
  <script type="text/javascript" src="bundle.js" charset="utf-8"></script>
</body>
</html>

Express’s static module will automatically use index.html as the index file in static directories, so now, if you’ll start web server using node server again and go to the http://localhost:3000/, you’ll see a blank page with title “Hello, world”.

Now, let’s build that bundle.js!

We are going to install webpack, a special plugin for it to compile babel javascript files and react. Yep, we are finally going to write something in React. :)

npm install webpack babel-loader react react-dom --save

After the dependencies installation, let’s create our client javascript file as src/client.js:

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
);

It does nothing but renders Hello, world! inside h1 element to container, which is an element with id=”root”.

We need to create that element in index.html. Simply add <div id="root"></div>:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Hello, world</title>
</head>
<body>
  <div id="root"></div>
  <script type="text/javascript" src="bundle.js" charset="utf-8"></script>
</body>
</html>

Now, to build bundle.js, let’s write a config file for webpack bundler:

module.exports = {
  entry: './src/client.js',
  output: {
    path: './public',
    filename: 'bundle.js'       
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      }
    ]
  },
  resolve: {
    extensions: ['', '.js', '.json'] 
  }
};

Save it as webpack.config.js in the project directory. What’s now? We need to run webpack in the way it will constantly watch and rebuild our bundle file; we also need to run our node server as its serves webpack’s bundle for us. To solve this, let’s write a simple script in package.json to simplify our work.

Before that, we’ll need one super-useful package called concurrently:

npm install concurrently --save-dev

After that, you’ll need to extend “scripts” section in your package.json to look like this:

  "scripts": {
    "webpack-watch": "webpack -w",
    "express-server": "node ./server",
    "dev": "concurrent --kill-others \"npm run webpack-watch\" \"npm run express-server\"",
    "test": "echo \"Error: no test specified\" && exit 1"
  }

And this is the final package.json:

{
  "name": "react-for-beginners",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "webpack-watch": "webpack -w",
    "express-server": "node ./server",
    "dev": "concurrent --kill-others \"npm run webpack-watch\" \"npm run express-server\"",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/viatsko/react-for-beginners.git"
  },
  "author": "Valerii Iatsko <dwr@codingbox.io>",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/viatsko/react-for-beginners/issues"
  },
  "homepage": "https://github.com/viatsko/react-for-beginners#readme",
  "dependencies": {
    "babel-loader": "^6.2.2",
    "babel-plugin-transform-class-properties": "^6.4.0",
    "babel-plugin-transform-runtime": "^6.4.3",
    "babel-polyfill": "^6.3.14",
    "babel-preset-es2015": "^6.3.13",
    "babel-preset-react": "^6.3.13",
    "babel-preset-stage-0": "^6.3.13",
    "babel-register": "^6.4.3",
    "express": "^4.13.4",
    "react": "^0.14.7",
    "react-dom": "^0.14.7",
    "webpack": "^1.12.13"
  },
  "devDependencies": {
    "concurrently": "^1.0.0"
  }
}

Now, Ctrl+C all the running processes of your application and try to use npm run dev to start it:

npm run dev

If everything went fine, you’d now see large Hello, world text on http://localhost:3000/:

hello world

Now you can play with React. If something went wrong, here’s the final code for this chapter https://github.com/viatsko/react-for-beginners/tree/58374deb088ec8ce3296898b10ae276897720829

© 2017 Valerii Iatsko. Personal opinions.
EN | RU