Setting Up Your React Dev Environment Easily

by kirupa   |   10 October 2016

The last major React-related topic we are going to look at is less about React and more about setting up your development environment to build a React app. Up until now, we've been building our React apps by including a few script files:

<script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>

These script files not only loaded the React libraries, but they also loaded Babel to help our browser do what needs to be done when it encountered bizarre things like JSX:

To review what we mentioned earlier when talking about this approach, the downside is performance. As part of your browser doing all of the page-loading related things it normally does, it is also responsible for turning your JSX into actual JavaScript. That JSX to JavaScript conversion is a time-consuming process that is fine during development. It isn't fine if every user of your app has to pay that performance penalty.

The solution is to setup your development environment where your JSX to JS conversion is handled as part of your app getting built:

With this solution, your browser is loading your app and dealing with an already converted (and potentially optimized) JavaScript file. Good stuff, right? Now, the only reason why we delayed talking about all of this until now is for simplicity. Learning React is difficult enough. Adding the complexity of build tools and setting up your environment as part of learning React is just not cool. Now that you have a solid grasp of everything React does, it's time to change that with this tutorial.

In the following sections, we're going to look at one way to set up your development environment using a combination of Node, Babel, and webpack. If all of this sounds bizarre to you, don't worry. You'll be on a first name basis with all of these tools by the end of it.

Onwards!

Meet the Tools

Ok, it is time to move further away from generalities (and sweet diagrams). It is time to get serious...er. It is time to meet the tools that we are going to be relying on to properly setup our development environment.

Node.JS

For the longest time, JavaScript was something you wrote to have things happen in your browser. Node.js changes all of this. Node.js allows you to use JavaScript to create applications that run on the server and have access to APIs and system resources that your browser couldn't even dream of. It is basically a full-fledged application development runtime whose apps (instead of being written in Java, C#, C++, etc.) are built and run entirely on JavaScript.

For our purposes, we are going to be relying on Node.js to manage dependencies and tie together the steps needed to go from JSX to JavaScript. Think of Node.js as the glue that makes our development environment work.

Babel

This one should be familiar to us! Simply put, Babel is a JavaScript transformer. It turns your JavaScript into…um...JavaScript. That sounds really bizarre, so let me clarify. If you are using the latest JavaScript features, older browsers might not know what to do when they encounter a new function/property. If you are writing JSX, well...no browser will know what to do with that!

What Babel does is take your new-fangled JS or JSX and turn into a form of JS that most browsers can understand. We've been using its in-browser version to transform our JSX into JavaScript all this time. In a few moments, you'll see how we can integrate Babel as part of our build process to generate an actual browser-readable JS file from our JSX.

Webpack

The last tool we will be relying on is webpack. It is known as a module bundler. Putting the fancy title aside, a lot of the frameworks and libraries your app includes have a lot of dependencies where different parts of the functionality you rely on might only be a subset of larger components.

You probably don't want all of that unnecessary code, and tools like webpack play an important role to allow you to only include the relevant code needed to have your app work. They often bundle all of the relevant code (even if it comes from various sources) into a single file:

We'll be relying on webpack to bundle up the relevant parts of the React library, our JSX files, and any additional JavaScript into a single file. This also extends to CSS (LESS/SASS) files and other types of assets your app uses, but we'll focus on just the JavaScript side here.

Your Code Editor

No conversation about your development environment can happen without talking about the most important tool in all of this, your code editor:

It doesn't matter whether you use Sublime, Atom, VisualStudio Code, TextMate, Coda, or any other tool. You will spend some non-trivial amount of time in your code editor to not just build your React app, but to also configure the various configuration files that Node, Babel, and WebPack need.

It is Environment Setup Time!

At this point, you should have a vague idea of what we are trying to do...the dream we are trying to achieve! We even looked at the various tools that will play a role in making this dream a reality. Now, it is time for the hard work to actually make everything happen.

Setting up our Initial Project Structure

The first thing we are going to do is setup our project. Go to your Desktop and create a new folder called MyTotallyAwesomeApp. Inside this folder, create two more folders called dev and output. Your folder arrangement will look a little bit like the following:

What we are doing here is pretty simple. Inside our dev folder, we will place all of our unoptimized and unconverted JSX, JavaScript, and other script-related content. In other words, this is where the code you are writing and actively working on will live. Inside our output folder, we will place the result of running our various build tools on the script files found inside the dev folder. This is where Babel will convert all of our JSX files into JS. This is also where webpack will resolve any dependencies between our script files and place all of the important script content into a single JavaScript file.

The next thing we are going to do is create the HTML file that we will point our browser to. Inside the MyTotallyAwesomeApp folder, use your code editor to create a new HTML file called index.html with the following contents:

<!DOCTYPE html>
<html>

<head>
  <title>React! React! React!</title>
</head>

<body>
  <div id="container"></div>

  <script src="output/myCode.js"></script>
</body>

</html>

Be sure to save your file after adding this content in. Now, speaking of the content, our markup is pretty simple. Our document's body is just an empty div element with an id value of container and a script tag that points to the final JavaScript file (myCode.js) that will get generated inside the output folder:

<script src="output/myCode.js"></script>

Besides those two things, our HTML file doesn't have a whole lot going for it. If we had to visualize the relationship of everything right now, it looks a bit like this:

I've dotted outlined the myCode.js file in our output folder because that file doesn't exist there yet. We are pointing to something in our HTML that currently is non-existent, but that won't stay that way for long.

Installing and Initializing Node.js

Our next step is to install Node.js. Visit the Node.js site to install the version that is appropriate for your operating system:

I tend to always install the latest version, so you should go with that as well. The download and installation procedure isn't particularly exciting. Once you have Node.js installed, test to make sure it is truly installed by launching the Terminal (on Mac), Command Prompt (on Windows), or equivalent tool of choice and typing in the following and pressing Enter:

node -v

If everything worked out properly, you will see a version number displayed that typically corresponds to the version of Node.js you just installed. If you are getting an error for whatever reason, follow the troubleshooting steps listed here.

Next, we are going to initialize Node.js on our MyTotallyAwesomeApp folder. To do this, first navigate to the MyTotallyAwesomeApp folder using your Terminal or Command Prompt. On OS X, this will look like the following:

Now, go ahead and initialize Node.js by entering the following:

npm init

This will kick of a series of questions that will help setup Node.js on our project. The first question will ask you to specify your project name. Hitting Enter will allow you to specify the default value that has already been selected for you. That is all great, but the default name is our project folder which is MyTotallyAwesomeApp. If you hit Enter, because it contains capital letters, it will throw an error:

Go ahead and enter the lowercase version of the name, mytotallyawesomeapp. Once you've done that, press Enter. For the remaining questions, just hit Enter to accept all the default values. The end result of all of this is a new file called package.json that will be created in your MyTotallyAwesomeApp folder:

If you open the contents of package.json in your code editor, you'll see something that looks similar to the following:

{
  "name": "mytotallyawesomeapp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}	  

Don't worry too much about the contents of this file, but just know that one of the results of you calling npm init is that you have a package.json file created with some weird properties and values that Node.js totally knows what to do with.

Installing the React Dependencies

What we are going to do next is install our React dependencies so that we can use the React and React DOM libraries in our code. If you are coming from a pure web development background, this is going to sound strange. Just bear with me on this.

In your Terminal or Command Prompt, enter the following to install our React dependencies:

npm install react react-dom --save	  

Once you Enter this, a lot of weird stuff will show up on your screen. What is happening is that the React and React-DOM libraries (and stuff that they depend on) is getting downloaded from a giant repository of Node.js packages.

If you take a look at your MyTotallyAwesomeApp folder, you'll see a folder called node_modules. Inside that folder, you'll see a bunch of various modules (aka what Node.js calls what we mere mortals just call libraries). Let's update our visualization of our current file/folder structure to look as follows:

The list of modules you see right now is just the beginning. We'll be adding a few more by the time you reach the end of this, so don't get too attached the number of items you see inside our node_modules folder :P

Adding our JSX File

Things are about to get (more!) interesting. Now that we've told Node.js all about our interest in React, we are one step closer towards building a React app. We are going to further enter these waters by adding a JSX file that is a modified version of the example we saw in the Components tutorial.

Inside our dev folder, using the code editor, create a file called index.jsx with the following code as its contents:

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

var HelloWorld = React.createClass({
  render: function() {
    return (
      <p>Hello, {this.props.greetTarget}!</p>
    );
  }
});

ReactDOM.render(
  <div>
    <HelloWorld greetTarget="Batman"/>
    <HelloWorld greetTarget="Iron Man"/>
    <HelloWorld greetTarget="Nicolas Cage"/>
    <HelloWorld greetTarget="Mega Man"/>
    <HelloWorld greetTarget="Bono"/>
    <HelloWorld greetTarget="Catwoman"/>
  </div>,
  document.querySelector("#container")
);	  

Notice that the bulk of the JSX we added is pretty much unmodified from what we had earlier. The only difference is that what used to be script references for getting the React and React DOM libraries into our app has now been replaced with import statements pointing to our react and react-dom Node.js packages we added a few moments ago:

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

Now, you are probably eagerly wondering when we can build our app and get it all working in our browser. Well, there are still a few more steps left. This is what the current visualization of our project looks like:

Our index.html file is looking for code from the myCode.js file which still doesn't exist. We added our JSX file, but we know that our browser doesn't know what to do with JSX. We need to go from index.jsx in our dev folder to myCode.js in the output folder. Guess what we are going to do next?

Going from JSX to JavaScript

The missing step right now is turning our JSX into JavaScript that our browser can understand. This involves both webpack and Babel, and we are going to configure both of them to make this all work.

Setting up Webpack

Since we are in Node.js territory and both webpack and Babel exist as Node packages, we need to install them both just like we installed the React-related packages.

To install webpack, enter the following in your Terminal / Command Prompt:

npm install webpack --save	  

This will take a few moments while the webpack package (and its large list of dependencies) gets downloaded and placed into our node_modules folder. After you've done this, we need to add a configuration file to specify how webpack will work with our current project. Using your code editor, add a file called webpack.config.js inside our MyTotallyAwesomeApp folder:

Inside this file, we will specify a bunch of JavaScript properties to define where our original, unmodified source files live and where to output the final source files. Go ahead and add the following JavaScript into it:

var webpack = require("webpack");
var path = require("path");

var DEV = path.resolve(__dirname, "dev");
var OUTPUT = path.resolve(__dirname, "output");

var config = {
  entry: DEV + "/index.jsx",
  output: {
    path: OUTPUT,
    filename: "myCode.js"
  }
};

module.exports = config;

Take a few moments to see what this code is doing. We defined two variables called DEV and OUTPUT that refer to folders of the same name in our project. Inside the config object, we have two properties called entry and output that use our DEV and OUTPUT variables to help map our index.jsx file to become myCode.js.

Setting up Babel

The last piece in our current setup is to transform our index.jsx file to become regular JavaScript in the form of myCode.js. This is where Babel comes in. To install Babel, let's go back to our trusty Terminal / Command Prompt and enter the following Node.js command:

npm install babel-core babel-loader babel-preset-es2015 babel-preset-react --save

With this command, we install the babel-loader, babel-preset-es2015, and babel-preset-react packages. Now, we need to configure Babel to work with our project. This is a two-step process.

The first step is to specify which Babel presets we want to use. There are several ways of doing this, but my preferred way is to modify package.json and add the following highlighted content:

{
  "name": "mytotallyawesomeapp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.5.0",
    "react": "^15.1.0",
    "react-dom": "^15.1.0",
    "webpack": "^1.13.1"
  },
  "babel": {
    "presets": [
      "es2015",
      "react"
    ]
  }
}	  

In the highlighted lines, we specify our babel object and specify the es2015 and react preset values.

The second step is to tell webpack about Babel. In our webpack.config.js file, go ahead and add the following highlighted lines:

var webpack = require("webpack");
var path = require("path");

var DEV = path.resolve(__dirname, "dev");
var OUTPUT = path.resolve(__dirname, "output");

var config = {
  entry: DEV + "/index.jsx",
  output: {
    path: OUTPUT,
    filename: "myCode.js"
  },
  module: {
    loaders: [{
        include: DEV,
        loader: "babel-loader",
    }]
  }
};

module.exports = config;

We added the module and loaders objects that tell webpack to pass the index.jsx file defined in our entry property through Babel to turn into JavaScript. With this change, we've pretty much gotten our development environment setup for building a React app.

Building and Testing Our App

The last (and hopefully most satisfying) step in all of this is building our app and having the end-to-end workflow work. To build our app, go back to our Terminal / Command Prompt and enter the following:

./node_modules/.bin/webpack

This command runs webpack and does all the things we've specified in our webpack.config.js and package.json configuration files. Your output in your Terminal / Command Prompt will look something like the following:

Besides seeing something that vaguely looks like a successful build displayed in cryptic text form, go to your MyTotallyAwesomeApp folder. Open your index.html file in your browser. If everything was setup properly, you'll see our simple React app displaying:

If you venture into the Output folder and look at myCode.js, you'll see a fairly hefty (~700Kb) file with a lot of JavaScript made up of the relevant React, ReactDOM, and your app code all organized there.

Conclusion

Well...so that just happened! In the preceding many sections, we followed a bunch of bizarre and incomprehensible steps to get our build environment setup to build our React app. What we've seen is just a very small part of everything you can do when you put Node, Babel, and webpack together. The unfortunate thing is that covering all of that goes well beyond the scope of learning React, but if you are interested in this, you should definitely invest time in learning the ins and outs of all of these build tools. There is a lot of cool things you can do.

If you have a question about this or any other topic, the easiest thing is to drop by our forums where a bunch of the friendliest people you'll ever run into will be happy to help you out!

THE KIRUPA NEWSLETTER

Get cool tips, tricks, selfies, and more...personally hand-delivered to your inbox!

( View past issues for an idea of what you've been missing out on all this time! )

WHAT DO YOU THINK?

NEWSLETTER

No spam. No fluff. Just awesome content sent straight to your inbox!

Awesome and high-performance web hosting!
BACK TO TOP
new books - yay!!!