Javascript Tutorial: How to set up Gulp for Developing ES2015 React v0.14+ Applications with Babelify & Browserify

I want to dedicate a post to show you how to set up Gulp and in particular, a set up for React v0.14 and up. I also focus on doing this in ES2015 (ECMAScript 6 or ES6). I have seen countless threads of people having trouble getting over this initial but important phase.

If you are looking to set up react with webpack, have a look at a detailed post I wrote on react + webpack. It includes things like hot module replacement.

If you just care about setting a project in ES6 with gulp, here’s another post. If you just want a base for ES6 and react then download this repo. It’s the same one we create in this tutorial.

What is Gulp?

Gulp is a task runner. It automates tasks that you have to do repeatedly when developing. A concrete example is having to compile your react component’s JSX to plain javascript every time you change something. Imagine having to do that all the time? No way. That’s why we need gulp.

How do I get it?

Gulp is very easy to get. First of, install nodejs and npm. If you have them, type this in your terminal:

npm install -g gulp

The -g is for global, so that it is available everywhere.

package.json

Before starting any project that will use gulp you need a package.json file in your project. Usually it is located in the root of the project. You don’t write this file, but rather generate it. Go to your terminal and in the root of your project type npm init this should take you to several steps to complete the package.json. You can just press enter on all steps to generate something quick.

setting up gulp dependencies in the package.json
how npm init should look like

gulpfile.js

The gulpfile is the file where you tell gulp what to do. It is usually located in the root of your project. Anything related to gulp goes there. It’s the only file you need to have for using gulp.

Let’s go over the code. First we declare the plugins we are going to use.

  • Gulp: Well, you know what this one is for: The task runner itself.
  • Browserify: Bundles your javascript files together and let’s you use modules that can be exported and imported in your javascript code.
  • vinyl-source-stream: Plugin used for working with stream outputs. Need this to work with Browserify easily.
  • gulp-util: Utility functions for gulp plugins, like nice logging.
  • babelify: This is our transpiler. It converts ES6 and JSX to plain old javascript. v6.0+ of babelify must include presets in order to work. Basically they did the same as react and are embracing the unix philosophy of how to build tools even more. So that means having more plugins that do one thing and do that one thing well.

Note: If you are using old gulpfiles babelify is going to cause pain for you, because of this change of separating the presets (like es6 and react) from the main plugin. You need to download the presets as well, more on this later.

We then define an array of dependencies (react and react-dom) which we will use later to tell browserify not to bundle them together with the app files, so that browserify doesn’t have to process them on each save. Think about it, they don’t need to get bundled each time you save your js files, they are libraries, they won’t change.

After that we initialise a counter that goes up each time gulp detects a change in the js files. More on this later.

Three gulp tasks are defined afterwards. “scripts” is the task fired when there’s a change in the js file. “deploy” is when we want to deploy to production. “watch” is the task that actually watches for changes in the js files. Use “gulp scripts” in the terminal for example if you want to fire the scripts task.

Later on we define a fourth task, the default one. Here we tell gulp to first fire the scripts task and then to start watching. We fire this task with “gulp” on the terminal. This is normally the only one you should use unless you want to deploy.

Now, inside both the “scripts” and “deploy” task we just see a call to the same function “bundleApp“. This function is where the bundling and conversion from JSX and ES6 to plain javascript happens.

Inside the function we first increase the counter. We then initialise browserify with some configurations passed in. We keep a reference under the variable “appBundler”.

After, we have a conditional block that will only execute if it’s the first time you run the “scripts” task. Note that it won’t run under the “deploy” task. What we do inside is to create another browserify object and bundle all our libraries together and save them as “vendors.js“. As I explained before, we do this so that when developing, you don’t have to rebundle all the libraries again (unnecessarily) as they don’t change. When deploying, we don’t want to have a separate “vendors.js” file, we want to have everything together under “bundle.js”, and preferably uglified to maximize performance.

We then have another conditional block that only lets you in if you’re in development mode (“scripts” task fired). It will tell the “appBundler” object not to bundle the dependencies we defined earlier. They are already bundled in “vendors.js”.

Finally, we fire the “appBundle” function so that it first transforms the JSX and ES6 (i.e. ES2015) and later bundle everything together in “bundle.js“. If you deploy with gulp deploy in your terminal, ALL your js files will be bundled to “bundle.js” including the libraries. This way, in your production environment you only have 1 script to rule them all!

Note: You can uglify the javascript files right after they are bundled, this will make your server happy. Search for the gulp-uglify plugin for more.

Installing Dependencies

Now we are going to download the development dependencies we listed earlier. This can be done as easy as putting the following code in your terminal:

sudo npm install --save-dev gulp browserify vinyl-source-stream gulp-util babelify babel-preset-es2015 babel-preset-react

You also need the dependencies for the project, which is just React for now. Since React 0.14 is out, you now need to install two packages instead of one: react and react-dom.

sudo npm install --save react react-dom

React Components

In the root of your project, create a folder called “app”. Then, inside it, create a file called “SearchableTable.js”.

Let’s use the same react component from one of the official react tutorials. It’s a filterable table but I transformed it to Javascript 6 and made it compatible with React v0.14. Put the following code in “SearchableTable.js”:

Things to note on React v0.14 for this component:

  • ReactDOM: ReactDOM is now the object that handles DOM operations for you component. This was separated from the react object to separate pure component definition with implementation (DOM or mobile) such as to pave the way for easir react + react-native integration.
  • DOM node refs: To get the value of the input in React v0.13 and under you would have used “this.refs.filterTextInput.getDOMNode().value”. The getDOMNode() was removed, as now the filterTextInput is the actual node itself. so in React v0.14 you use “this.refs.filterTextInput.value”.

Let’s also define the data this app will use. Put the following code in a file called “data.js”, also under the “app” folder.

Now we need a file where we import the react component and pass it the data it’s going to use. Create a file called “app.js” also under the “app” folder and put the following code:

This will be the file where you do other stuff for your app in the future. You see we are using ES6 in these files. For example we use “import” to import modules and other files.

HTML

Our app needs some html to work. Let’s keep it minimal. Create a file called “index.html” on the root of your folder.

Simple, we put up a container with id “searchableTable” which is where the component is going to mount on. We also load the two javascript files: vendors.js and bundle.js.

Closing

Your project structure should look like this:

projecttree

In your terminal, type “gulp” in the root of the project to fire gulp and let it bundle everything when there’s a change in the js files.

Once it’s done, test your project in your browser. Either navigate to the file or in the terminal go to your project’s root and type:

python -m SimpleHTTPServer 3000

You can then go to your browser and navigate to: http://localhost:3000/

Your project should look like this:

projectexample

Typing in something should filter the table. Congrats! If for some reason your project doesn’t run, here’s the repository for this project.

Author: JP

Javascript jedi padawan.

  • Oron Ogdan-Adam

    Great writeup. How do you maange the versioning of vendors.js and bundle.js to bust the browser cache when they change ? how can I use gulp automagically to do that for me and replace the ref in the HTML.

    • Jean-Pierre Sierens

      Thanks! There’s gulp plugins out there that you can use to help you bust compiled files. Check out https://www.npmjs.com/package/gulp-buster for example.

      Thanks to gulp’s plug and play mentality, you just need to plug gulp-buster in the right place and it should work. Try putting it right after line 83 of your gulp.js file. Should be something like this:

      .pipe(gulp.dest(‘./web/js/’))
      .pipe(bust())
      .pipe(gulp.dest(‘./web/js/’));

      Check out the plugins documentation if that doesnt work. Hope that helps

  • samirgh

    Hey thanks for the awesome tutorial. Only thing that bugged me was that filtering is case sensitive. Eg search “f” (for “Football”) shows no results but thats just minor detail! Thanks again

    • Jean-Pierre Sierens

      You’re welcome! Yes, I left that out, my bad :) Comparing the two values in lowercase should fix that

  • Spencer Bigum

    If I wanted to use JSX files instead of JS files – could I just change the ENTRIES point to ‘app/app.jsx’ for example? And then put a watcher on any JSX file instead of JS file? Or would the watcher stay on the compiled JS file?
    Great job on explaining everything, still personally like Gulp better than webpack, but I do know Gulp better than Webpack :)

    • Jean-Pierre Sierens

      Hello and thanks!
      It should be as easy as changing the entries to app.jsx and also the watcher to watch for jsx files instead of js. Try it out, let me know!

  • Pingback: Javascript Tutorial: How to set up Gulp for Developing ES2015 React v0.14+ Applications with Babelify & Browserify – Javascript Jedi Padawan – ReactJS News()

  • Christian Hoffart

    every time you deploy your app for production you remove the vendor.js from index.html?

  • Jag

    I was looking just for ES2015 and webpack and I somehow got landed here. This is just a wonderful article covering gulp and ES2015 and react. If any of you guys are looking for ES2015 and webpack, I came across this: https://www.youtube.com/watch?v=wy3Pou3Vo04

    Hopefully, it helps future readers.

  • Pingback: How to avoid bundling ReactJs multiple times using Gulp? - PKT()

  • aftabnaveed

    When I try to import React from ‘react’; it throws this error Cannot find module ‘react’ I have react installed locally through npm install react

  • Дмитрий Федоров

    Thank you very much! Good stuff!!!

  • Andy

    If you do run the gulp deploy command and deploy with a single bundle.js file, wouldn’t you want to remove the vendors script tag from index.html? And if so, is there a way to automatically update the html to remove that script tag for production, but leave it there when the production flag is false?

  • Matyi a Zigasságos

    Thanks a lot! I googled days to find your post! Endless a working example for dummies :) Thank you!
    One question only: Is there a way to integrate uglyfy or minify to compress the results?