Fig. 11 A Guide for Developers

React.js From Scratch: Part 4 — Your Environment

The one where we actually build something with code.

Part 1 can be found here, and Part 2 is over here. Lo and behold, Part 3 is over here.


Let’s get right to it. In this guide, we will set up a new project complete with a package.json file and a gulpfile.js file. We’ll dive in and explain each necessary task module to get React up and running. Also, we will get some helpful plugins installed for text editors and the Chrome browser.

Step 1: Installing Node.js

Node is a JavaScript engine that runs outside of a browser. It enables awesome JavaScript tools to run on your system as normal applications. Primarily, Node is used to author web applications, but we will be simply using it to install and run our Gulp tasks. To check if you have Node installed (and which version it is), run node -v in Terminal.app.

From here on out, the instructions will be catered towards Mac OS X users. However, many of these these instructions should work on Windows as well. Most of the work will be done in the Terminal, a text editor of your choice, and the Chrome browser.

If the node command is not found, you can download the installer from the Node website. The installer includes the Node binary as well as npm, or Node Package Manager.

npm is the tool we will be using to install all necessary modules used with React and Gulp.

As of this writing, the latest stable version of Node is 5.6.0, and npm is 3.6.0

Once Node and npm are installed, let’s start a new project!

Step 2: The package.json file

Every Node project contains a package.json file. This file resides in the root of the project and contains meta information about the project such as name, version, and description. It also manages project dependencies for npm. For example, if you were to clone a git repository locally, running npm install in the project directory would automatically install each module required to run and develop the project. It’s much easier than hunting down and installing each individual module for each project. Everything is self-contained and it’s wonderful.

Let’s create a new project and build a blank package.json file. In the Terminal, we will create a place to store your project. If you have a directory you prefer, change to that directory (cd). If not, let’s create a “Code” directory inside your home directory.

From the Terminal, type mkdir -p ~/code/react-project && cd ~/code/react-project. This creates the directory and immediately moves us inside it. The prompt should show this. For Windows users, the %HOMEPATH% alias acts the same as ~.

Now we have a blank directory and we are sitting inside it. From here, you can either open up the directory as a project in your favorite text editor or you can run the npm init command to generate a package.json file through a helpful wizard. If you want to create it through the editor, copy and paste the following into a blank file, saving it as package.json.

{
  "name" : "react-project",
  "version" : "0.0.0"
}

Otherwise, run npm init and accept all the defaults.

At this point, you should have a directory called react-project inside the ~/code/ directory. The only thing in the react-project directory is a package.json file. If you open that directory inside a text editor, it should look something like this:

Project screenshot

If you used npm init to create the package.json file, it may have more information in it. This won’t affect anything.

Now, let’s start adding some project dependencies.

Step 3: npm module installation

There are several dependencies that are required to run a local React project environment. We will start with the bare minimum amount to get you up and running, then add some helpful extras to make things speedier. Let’s start with the obvious one: React.

Install React

React has been split into two separate libraries: React and ReactDOM. React is all the core elements of the library. ReactDOM allows the developer to interact with the DOM.

To install these two modules with npm, run the following command in the root of your project:

If you are unsure where you are in the terminal, run pwd to see the current working directory. When all else fails,cd ~/code/react-project will get you to the correct folder.

npm install --save react react-dom

The two modules will now be installed. A node_modules folder will appear in your project tree. The --save flag will edit your project.json file to add react and react-dom as dependencies. They are listed by module name (alphabetically) and version number.

{
  "name": "react-project",
  "version": "0.0.0",
  "dependencies": {
    "react": "^0.14.7",
    "react-dom": "^0.14.7"
  }
}

As we go through the next steps, more dependencies will be added to the file. Some will be added to the dependencies node in the package.json file, others will be added to devDependencies. The difference is that dependencies are used for the actual production environment of the project, devDependencies are used only for your development environment. Once it’s complete, all dependencies can be installed by running npm install in the project directory. This is helpful for bootstrapping the project on another developer’s computer as the node_modules folder is not typically included in source control.

Let’s continue.

You, Your Tooling, and You

Here’s where things get crazy. At this point, we need to install all the necessary tooling to get anything React to appear in your browser. We will need a bunch of different things, so I will call out each tool and what it is used for.

1. Gulp

The first obvious Gulp step is to install Gulp. This is the engine through which everything else runs.

npm install --global gulp-cli

This installs the gulp command in the terminal. The --global flag means it’s a system-wide install and the command can be used everywhere.

npm install --save-dev gulp

This adds the gulp module to your local project. --save-dev adds it as a devDependencies item in the package.json file.

That was easy.

2. Gulp Utilities

We will be using gulp-util’s log() function to log step completion to the command line. You can check out all the other fun tools on the gulp-util Github repo readme.

npm install --save-dev gulp-util

3. Babel for Gulp

npm install --save-dev gulp-babel

This is our transpiler to convert ES6 (ES2015, ES2016) and JSX syntax into something the browser can understand. The previous version of Babel came with everything necessary to transpile to ES6 out of the box. Unfortunately, this is no longer the case. Additional plugins, or “presets”, are required for Babel to actually do anything. Yay.

npm install --save-dev babel-preset-es2015 babel-preset-react

We’ll return to this later.

4. BrowserSync

Hoo boy, this is a fun one. BrowserSync is a fantastic tool that syncs your browser with the current state of your assets. Basically, you save a change in a file and the browser automatically refreshes. It also allows syncing to mobile browsers with the help of xip.io.

You may want to --globally it since it’s a tool that can be used in any web development project (yeah I just used a command flag as a verb).

npm install --save-dev browser-sync

5. Browserify, Babelify, and Watchify

Browserify allows Node module usage inside of our JS files. require() is a thing you will see a lot of. Babelify is a Browserify transformation mode that bundles AND transpiles to ES5. In addition, we need the module Watchify to look for code changes to re-run the Babelify task.

npm install --save-dev browserify babelify watchify

6. Vinyl Source Stream

Vinyl Source Stream makes it easy to use one streaming method between multiple modules. Some modules have their own way to pass information along, but making them work with other modules could be tricky. This is an under-the-hood tool that makes our code simpler than it would be otherwise.

npm install --save-dev vinyl-source-stream

Any additional modules we install will be completely optional I will call them out as such.

Step 4: Create Our Gulpfile

Now we need to actually wire up our tooling, so a gulpfile.js file should first be authored. This may get heavy, but I am still going for the most minimal React development environment I can muster. It will also contain some simple conveniences.

In your text editor of choice (with the react-project project open), create a new file in the project root called gulpfile.js.

The most basic gulpfile.js looks like this:

var gulp = require('gulp');

gulp.task('default', function() {
  console.log("hey y'all");
});

Go ahead and copy/paste this code into your blank gulpfile.js. Run the gulp command in the project root to see the default task being run. You should see my friendly console.log() message written out.

Now it’s time to make Gulp useful.

Step 5: Edit Our Gulpfile

We’re going to be editing the default task first by adding in the BrowserSync initializer.

var gulp = require('gulp');
// add the browserSync module reference
var browserSync = require('browser-sync').create();

gulp.task('default', function() {
  browserSync.init({
    server: "./"
  });
});

Awesome. We are just starting BrowserSync when the gulp command is executed. In this case, BrowserSync starts a server in the root (./) of the project. But, because there is no index.html file in your project root, one will need to be created for the server to start properly.

Create a new file called index.html, and fill it with the following markup:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello</title>
  </head>
  <body>
    <h1>Hello!</h1>
  </body>
  <!-- Doesn't yet exist, but it will in a couple minutes -->
  <script src="dist/bundle.js" charset="utf-8"></script>
</html>

Save it, then run the gulp command. Your default browser will open a new tab pointed to localhost:3000. “Hello!” should be the only thing appearing on the page.

Time to add a lot of complexity. To kick things off, let’s add all our dependencies to the top of the gulpfile.js.

// gulpfile.js
var gulp        = require('gulp');
var gutil       = require('gulp-util');
var source      = require('vinyl-source-stream');
var babelify    = require('babelify');
var watchify    = require('watchify');
var browserify  = require('browserify');
var browserSync = require('browser-sync').create();

From here, let’s create our browserify/babelify/watchify combination. This is a bit strange, so I will annotate the additions. Add these lines directly below the module definitions and before the default gulp task.

// we are creating a bundler instance which
// accepts a script.js file in the /src directory
// we use bundler to complete all the js tasks

// the debug arguments are for the creation of sourcemaps
watchify.args.debug = true;

var bundler = watchify(browserify('./src/script.js', watchify.args));

// We are telling bundler to use the Babel presets
// es2015 and react (for JSX transpilation)
bundler.transform(babelify.configure({
  presets: ["es2015", "react"]
}));

// When the bundler has detected a change, rebundle
bundler.on('update', bundle);

// The function that bundles
function bundle() {

  // remember gulp-util? Here's the usage of the log() function
  gutil.log('Bundling...');

  return bundler.bundle()
    .on('error', function (err) { // on error, let us know
      gutil.log(err.message);
      this.emit("end");
    })
    .pipe(source('bundle.js')) // the bundled file is passed along...
    .pipe(gulp.dest('dist')) // ...then spit out into the dist directory
    .pipe(browserSync.stream({ once: true })); // update the browser
}

// run "gulp bundle" as a command (optional)
gulp.task('bundle', function () {
  return bundle();
});

That’s a lot to take in, but there is one more step. We need to wire this up to the default gulp task. Let’s make a couple changes to the default task we started with.

// same as before, but we are running the "bundle"
// function defined above as well
// after "bundle" runs, browserSync starts up
// and waits for changes
gulp.task('default', ['bundle'], function () {
  browserSync.init({
    server: "./"
  });

  // added a gulp watch function that reloads the browser
  // any time a change is made to the index.html file
  gulp.watch('index.html', function() {
    browserSync.reload();
  })
});

Alright! Now we have a fully functional (barebones-ish) Gulpfile with BrowserSync and a bundle task that watches for each change to your /src/scripts.js file. It’s ready for any and all ES6/JSX you throw at it. There are no css compilation tasks yet because they aren’t required to get rolling with React, but we can always add one later. It’s extremely easy to add an additional watch task.

We aren’t minifying our scripts either, yet.

If Sass isn’t your cup o’ tea, there are similar gulp tasks for LESS and Stylus.

At this point, your gulpfile.js should look like this:

// gulpfile.js
var gulp        = require('gulp');
var gutil       = require('gulp-util');
var source      = require('vinyl-source-stream');
var babelify    = require('babelify');
var watchify    = require('watchify');
var browserify  = require('browserify');
var browserSync = require('browser-sync').create();

watchify.args.debug = true;
var bundler = watchify(browserify('./src/script.js', watchify.args));

bundler.transform(babelify.configure({
  presets: ["es2015", "react"]
}));

bundler.on('update', bundle);

function bundle() {

  gutil.log('Bundling...');

  return bundler.bundle()
    .on('error', function (err) {
      gutil.log(err.message);
      this.emit("end");
    })
    .pipe(source('bundle.js'))
    .pipe(gulp.dest('dist'))
    .pipe(browserSync.stream({once: true}));
}

gulp.task('bundle', function () {
  return bundle();
});

gulp.task('default', ['bundle'], function () {
  browserSync.init({
    server: "./"
  });

  gulp.watch('index.html', function() {
    browserSync.reload();
  })
});

For a better view, consult this gist.

Let’s set up the rest of your project. 👍

Step 5: Creating a Scripts.js File

At this point, we have a Gulpfile with a single index.html document at the project root. A package.json file also remains. Nothing is going on yet.

Create a src directory and place a blank script.js file in it. This is our project entry point. If you run gulp bundle in the command line, you will see a new directory called dist appear with a single bundle.js file in it.

Cool, now execute the gulp command to get your server running.

The only thing left for this file is to write some code into it. For now, you can add a simple console.log('hello') call, save, let Gulp do its thing, then look at the console in the browser. You should see a “hello” log.

I created a repo on Github for this state of the project. You can grab the code from the repo here.

Yay! We have a dev environment! If you wish to stop the server, hit Control + C in the command line.

Bonus: A list of helpful plugins

I use Atom as my text editor. The only plugin that is required for authoring anything for React is the language-babel grammar. It adds to Atom the ability to correctly parse ES6/JSX code complete with code hinting. It’s nice. Download it.

A similar plugin for Sublime Text 3 exists which is authored by the Babel team. Download it if you are a Sublime user.

Finally, once we get into the React bits, Facebook created a nice Chrome plugin that helps debug a React environment. Download it to prep for the next steps.


Next time in Part 5 we will code a small React example. As you can see, there are a lot of prerequisites to getting started. The good thing is that we are finally ready to move forward. Stay tuned!

Actually, it’s out now. Continue?


Further Reading

Written by Andy Rossi Published on February 18, 2016