React tutorial: Components with and without ES6, including tooling with Babel, Npm and Webpack

React is a JavaScript library designed to create UI (User Interface) components. However, because React is small and excels at what it does, it's inevitably used with hundreds -- perhaps even thousands -- of other JavaScript libraries and frameworks. Therefore seeing project spin-offs named React-<blank> or writings titled React with <blank> has become the norm rather than the exception. What you'll read next is exclusively centered on React with the only assumption being you're familiar with some of JavaScript's earliest concepts like events, DOM & jQuery -- reading the previous section What is JavaScript ? What is modern JavaScript ? should be enough to get you through this React tutorial.

React is small, but it does have its own particular syntax, development and deployment process, which is why it can feel overwhelming on many fronts to new users. Because of this, I'll start with a jQuery example explained previously and create equivalent React examples so you have a basis for comparison. The following example illustrates this jQuery web page that uses a couple of events linked to a button and an AJAX call.

React components are relatively easy to understand, but what steepens React's learning curve is there are multiple ways to develop React components, as well as multiple ways to deploy React. React started prior to ES6, which was a major JavaScript milestone version that introduced simpler syntax to work with OOP (Object Orientated Programming) classes, objects and inheritance. Because ES6 is still not mainstream, React components continue to support their old ad-hoc class syntax, as well as a newer ES6 class syntax. In addition, React components use a markup language called JSX that must be converted to plain JavaScript, which in turn creates multiple deployment alternatives. So React concepts account for at most 30% of the learning curve, while the remaining 70% consists of learning different React syntax and tools required to deploy React.

In the first part of this tutorial, I'll stick to exploring React component concepts and syntax, using the simplest deployment alternative which consists of browsers doing pre-processing & downloading multiple libraries to run React components. In the second part and once you get a feel for React itself, I'll discuss how to pre-process and bundle React using two of the most popular modern JavaScript tools: npm & webpack.

Part I: React component concepts, with and without ES6

The following examples represent equivalent React web pages of the previous jQuery example. Both React examples produce the same result, except one uses React's ad-hoc class syntax and the other React's ES6 class syntax.

JSX, <script type="text/babel">, babel and transpiling

If you skim through either main index.html page in the previous React examples, you can see the overall web page structure isn't very different from non-React web pages. That is, there are <script> elements to import resources, a <head> and <body> element, as well as standard HTML elements like <div>, <h4> and <button>. However, although the inline JavaScript is wrapped in a regular <script> element, notice it uses the type="text/babel" attribute.

React uses a JavaScript-like syntax named JSX to make it easier to declare components. You don't have to use JSX, but using JSX will definitely make it more enjoyable to work with React. To give you an idea, the following snippet shows the React components from the previous examples with inline JSX and its equivalent plain JavaScript.

React component with inline JSX and equivalent JavaScript transpiled from JSX

// React component with inline JSX (React ad-hoc class syntax)
var Banner = React.createClass({ 
   render: function() { 
      return (
      <div className={this.props.show ? '' : 'hidden'}>{this.props.message}</div>
      );
    }
});

// React component with inline JSX (React ES6 class syntax)
class Banner extends React.Component { 
    render() { 
       return (
       <div className={this.props.show ? '' : 'hidden'}>{this.props.message}</div>
       );
    }
}



// React component transpiled to JavaScript 
'use strict';

var Banner = React.createClass({
  displayName: 'Banner',

  render: function render() {
    return React.createElement(
      'div',
      { className: this.props.show ? '' : 'hidden' },
      this.props.message
    );
  }
});

The key piece of syntax is the return value of the render() method. Both left-hand side versions return a JSX snippet which you can see has a more markup feel to it, like a lot of UI syntax (e.g. HTML, XML). On the other hand, the right-hand side has a more programmatic feel to it being plain JavaScript. If you think you would be more comfortable writing something like the right-hand side (i.e. plain JavaScript) instead of either left-hand side version (i.e. JSX), congratulations, you can skip to the next section and never hear from JSX again. If you're like most of us though, you'll come to rely on JSX to use React.

As helpful and friendly as JSX is to define JavaScript components, it's not JavaScript, but rather a language that produces JavaScript. This means that in order for browsers to interpret JSX, JSX needs to be converted to plain JavaScript, which is where the text/babel attribute for the <script> tag used in both examples comes into play.

Near the top of both index.html web pages you can see we import babel-core/5.8.24/browser.js. This library is tasked with looking for <script type="text/babel"> tags and transforming their contents from JSX to plain JavaScript.

This transformation process known as transpiling -- described earlier as part of Modern JavaScript essentials -- is done directly on a user's browser through the babel library in both these examples. However, be aware that performing the transpilation process on a user's browser and sending the babel library over a network for this purpose, should only be done in limited circumstances like these examples.

For real life applications, the transpilation process for JSX should be done as part of the deployment process, so end users receive plain JavaScript in their browsers. This in turn speeds up the web page, since it reduces the work needed to be done by a browser and also reduces the amount of ancillary downloads required for the transpilation process. The second half of our React discussion describes how to integrate transpilation as part of the deployment process. Next, I'll continue discussing these same examples that rely on an end user's browser doing the transpilation process.

Render React components on web pages

React components are rendered on web pages by appending them to standard HTML elements, similar to how you append HTML nodes on web pages with jQuery or standard DOM. The following snippet illustrates the relevant parts to render a React component, taken from the index.html web page in the previous examples.

Render React component to web page

 <body>
    <div id="banner-container"></div>
    
    <script type="text/babel">

    ReactDOM.render(
       <BannerContainer message="React 101!"/>,document.getElementById('banner-container')
    );
      
      
    </script>
 </body>

In this snippet you can see the standard HTML element <div id="banner-container"></div> that's used to append a React component. Next, in the <script> section is a call to ReactDOM.render() which takes two arguments. The first ReactDOM.render() argument is the React component you want to render, in this case <BannerContainer> with the message="React 101!" attribute. The second ReactDOM.render() argument is the HTML element on which you want to append the React component, in this case we use the standard DOM document.getElementById() method to reference the HTML element with id="banner-container".

And that's all there is to rendering a React component on a web page. If you want to render the same React component on multiple HTML elements you can broaden the matching pattern, just as you can use the ReactDOM.render() statement multiple times to render different React components.

Next, our focus will shift to the actual structure of a React component. As I mentioned at the start, there are two ways to develop React components. I'll first describe React's ad-hoc pre-ES6 class syntax and later describe React's ES6 class syntax. Both techniques produce the same results, so the next two sections are complementary to one another.

React components with ad-hoc class syntax (pre-ES6)

A React component can be created using React's React.createClass() method. Inside the React.createClass(), you can declare React's life-cycle methods, custom methods, as well as the actual HTML the component generates. The general idea of a React component is to encapsulate all actions and markup in the same place, unlike it's done in something like jQuery where HTML and JavaScript are declared separately. The following listing illustrates the structure of the <BannerContainer> component used in the example that uses ad-hoc React class syntax.

React component structure with createClass()

 var BannerContainer = React.createClass({
        getInitialState: function() {

        },
        handleClick: function(event) {

        },
        handleAjaxButtonClick: function(event) { 

        },
        render: function() {
           return (
             <div>
               <h4>.....</h4>
             </div>
           );
        }
    });

The method you'll end up using most in React components -- which is a requirement -- is the render() method which defines the HTML for the component. This means that whenever you render the <BannerContainer> component from this snippet, React outputs the HTML <div><h4>.....</h4></div>.

In addition, in this component there are two types of React component methods: life-cycle methods that are invoked automatically and custom methods that need to be manually hooked-up to triggers. The render() method is a life-cycle method that outputs the component's HTML and the getInitialState() method is another life-cycle method that initializes a React component's state. The handleClick and handleAjaxButtonClick methods are custom methods that need to be hooked up to triggers (e.g.click, hover) as part of the HTML in the render() method.

In React components you can use the this keyword to reference the current instance of a component inside any method. The this reference is standard in JavaScript and used widely in other JavaScript libraries like jQuery, so there's nothing much to explain about it. However, React components also make use of two references that are basic to handle component data: props and state.

In very simple terms, data in props can only be set and not changed (i.e. it's immutable), while data in state is meant to keep track of changing values in a component. The following listing shows the <BannerContainer> component with various this, props and state references.

React component use of this, props and state


 var BannerContainer = React.createClass({
        getInitialState: function() {
	    return {showBanner: true, message: this.props.message};
        },
        handleClick: function(event) {
	    this.setState({showBanner: !this.state.showBanner, message: this.state.message});
        },
        handleAjaxButtonClick: function(event) { 
            // Omitted for brevity
        },
        render: function() {
           return (
             <div>
               <h4><button onClick={this.handleClick}>Click to {this.state.showBanner ? 'hide' : 'show'} {this.state.message}</button></h4>
               <Banner show={this.state.showBanner} message={this.state.message}/>
               <h4><button onClick={this.handleAjaxButtonClick}>Click to update message via AJAX</button></h4>
             </div>
           );
        }
    });

 ReactDOM.render(
       <BannerContainer message="React 101!"/>,document.getElementById('banner-container')
    );

The following sequence of events takes place in the previous listing:

  1. The ReactDOM.render() method is called to render the <BannerContainer> component with the message="React 101!" attribute.
  2. The component's message="React 101!" attribute becomes accessible through this.props.message inside the component.
  3. The component's getInitialState() life-cycle method is called and sets two values {showBanner: true, message: this.props.message} with the intent to change them. Note this new message reference gets its initial value from this.props.message and is redefined in this manner because this.props.message is immutable.
  4. The references set in getInitialState() become accessible through this.state.<reference_name> (e.g.this.state.showBanner, this.state.message).
  5. The handleClick() method uses the setState() method to update state reference values.
  6. Finally, the render() method contains the component's HTML output with various statements that make use of this.state values and hooks to the component's methods that alter this.state values.

As you can now understand based on this sequence of events, a React component relies on the this.props and this.state references to set values for the component's rendered HTML. In the case of this.props these values won't change in the HTML due to their immutable nature, however, those in this.state are updated dynamically -- depending on trigger events -- and the HTML is updated accordingly.

React components with ES6 classes

The previous React component uses the initial incarnation of React components. But as with all things technology, React now offers an alternative way to construct React components based on ES6 classes. With ES6 being a newer JavaScript standard, React components using ES6 classes are becoming all the more common. Albeit, since ES6 still isn't mainstream, both React component techniques continue to be perfectly valid and supported.

An ES6-based React component can be created using React's React.Component class. To create a React component in this manner you must use the ES6 class and extends keywords to create a class that inherits its behavior from React.Component. Method declarations in React ES6 classes -- including life-cycle, custom methods and the actual HTML the component generates -- are different than those used in the first type of React components, mainly because ES6 enforces its own way of doing things. The following listing illustrates the structure of the <BannerContainer> component used in the example that uses React ES6 class syntax.

React component structure with React.Component

class BannerContainer extends React.Component { 
        constructor(props)  {
	    super(props);
	    this.handleClick = this.handleClick.bind(this);
	    this.handleAjaxButtonClick = this.handleAjaxButtonClick.bind(this);

        }
        handleClick(event) {

        }
        handleAjaxButtonClick(event) { 

        }
        render() {
           return (
             <div>
               <h4>.....</h4>
             </div>
           );
        }
    }
      

The render() method continues to be the most important method for this other way of creating React components, since it defines the HTML for the component. So whenever you render the <BannerContainer> component from this snippet, React outputs the HTML <div><h4>.....</h4></div>. The only difference in the render() method between component types is the syntax, the ES6 component version is cleaner since it isn't wrapped around function() syntax. But things do change a little more with other component methods.

Notice there's no getInitialState() method and the React component now has a constructor() method that wasn't there before. ES6 classes use a special method called constructor() -- like other OOP languages -- to initialize object instances. Because the React component is now ES6 compliant, it relies on the constructor() method to initialize the React component and forgoes using the custom initializer getInitialState() method.

Custom methods on ES6 class-based React components also require additional attention. In the prior React component version, custom methods (e.g. handleClick, handleAjaxButtonClick) were automatically bound to the instance. Following the semantics of regular ES6 classes, custom methods used in React ES6 class-based components must be explicitly binded [1]. This binding process for custom methods is done in the constructor() method as you can see in the last listing (e.g. this.handleClick = this.handleClick.bind(this);, this.handleAjaxButtonClick = this.handleAjaxButtonClick.bind(this);).

In ES6 class-based React components, the use of the this keyword, as well as React's props and state references function practically the same, as you can see in the following listing

React ES6 class-based component use of this, props and state

class Banner extends React.Component { 
      render() { 
           return <div className={this.props.show ? '' : 'hidden'}>{this.props.message}</div>
        }
}

class BannerContainer extends React.Component { 
        constructor(props)  {
	    super(props);
	    this.handleClick = this.handleClick.bind(this);
	    this.handleAjaxButtonClick = this.handleAjaxButtonClick.bind(this);
	    this.state = {showBanner: true, message: props.message};
        }
        handleClick(event) {
            this.setState({showBanner: !this.state.showBanner, message: this.state.message});
        }
        handleAjaxButtonClick(event) { 
            // Use fetch lib for AJAX, as React doesn't include AJAX support
	          fetch('https://jsonplaceholder.herokuapp.com/posts/1')
	          .then(function(response) {
         	      return response.json()
	          }).then(function(json) {
	              console.log(json);
                this.setState({'message': json.title});
	          }.bind(this));
        }
        render() {
           return (
             <div>
               <h4><button onClick={this.handleClick}>Click to {this.state.showBanner ? 'hide' : 'show'} {this.state.message}</button></h4>
               <Banner show={this.state.showBanner} message={this.state.message}/>
               <h4><button onClick={this.handleAjaxButtonClick}>Click to update message via AJAX</button></h4>
             </div>
           );
        }
   }

ReactDOM.render(
       <BannerContainer message="React 101 (ES6 classes)!"/>,document.getElementById('banner-container')
);

As you can see in this last listing, with the exception of a few minor syntax difference, the use of this, props and state, as well the component workflow, is the same as the one described in the previous component version that uses React's pre-ES6 ad-hoc class syntax.

React component relationships and UI purity

Another important aspect of React components is they can be nested -- irrespective of the approach you decide to take, ES6 classes or classical classes -- effectively establishing relationships. If you look at the render() method in either <BannerContainer> component in the last listings you can see the <Banner show={this.state.showBanner} message={this.state.message}/> statement. This reference tells React to render another React component named <Banner> in this position of the HTML hierarchy. Notice this other <Banner> component -- the child -- is defined with two properties or state values taken from the <BannerContainer> component -- the parent.

This ability to create parent-child relationships between React components creates very powerful options. For example, changes in one component can be propagated to other components so that when an event happens (e.g. click, data update) the other components react to this change and take the appropriate actions.

Another important factor of React components is you can expect a lot of UI functionality, but not much of anything else. If you look at the handleAjaxButtonClick() method in the previous examples, you can see this method contains logic that makes an AJAX call. If this last AJAX call is successful, it takes the result and updates the component's message state variable. The interesting bit about this last method is that it uses the fetch JavaScript library to make the AJAX call -- a library you can also see declared in a <script> tag at the top of the index.html page.

The use of this additional library for the simple task of an AJAX call shows just how specific the functionality offered by React is. After various React versions, it remains to be seen for React to expand beyond its core feature set to build UI components. This is a positive sign that shows how React is committed to UI functionality, compared to other JavaScript libraries that expand on non-essential features in an attempt to gain greater traction and support, a phenomenon which is all too common in JavaScript circles where dozens of libraries overlap trying to solve the same problem.

Now that you've explored React's component concepts and syntax, as well as seen working examples of React components, it's time to move on to a React deployment process that's more inline with a real life project.

Part II: React deployment with npm and webpack

As you're now aware, React components -- specifically JSX -- cannot be delivered 'as is' to a browser, they must be converted to plain JavaScript. In the React examples you just saw, a special transpiler library called Babel was added to the web page so it could be downloaded by a browser to perform the JSX conversion into plain JavaScript. This is less than ideal, because not only does this place additional load on an end user's browser, it also forces him to download an additional dependency.

Also, if you consider these past React projects are accompanied by multiple dependencies -- two React js files & the fetch library for AJAX -- it begets the question "Wouldn't it be better to bundle JavaScript dependencies so an end user downloads a single js file ?" It definitely is the recommended approach. And because React is often accompanied by many more dependencies on medium to large projects (e.g. a SPA with dozens or hundreds of JS libraries), bundling JavaScript dependencies has become a standard practice for both React projects and modern JavaScript deployments.

Npm package manager

The first thing you need for this type of JavaScript deployment is a package manager. We will use npm which is included with Node.js -- the JavaScript server side platform. Node.js is a widely used platform, so there are installers for all the major operating systems (Windows, Apple & Linux), as well as the source code if you use an esoteric operating system. Once you download Node.js [2] and install it, the npm executable is included with the installation.

Go ahead and type npm on a command-line prompt/shell and you will see the default output message that starts with Usage: npm <command>. If npm is not found or you get an error, it means you didn't install Node.js correctly. Npm has excellent documentation [3] and there are many forums (e.g. stackoverflow.com) to ask installation troubleshooting questions, so I'll leave the npm installation topic at this.

With access to npm create a folder for the project (e.g.reactintro) and type the following npm command.

Create npm project without prompt

  # The -y flag creates a project file without prompt using default values
  npm init -y

This last command creates a package.json file with the configuration of a newly minted JavaScript project. If you open the file, it should look like this other listing.

npm project configuration package.json file

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

Don't worry about the meaning of each package.json line for the moment, let's install some dependencies. If you recall from the examples in part I, they used the fetch library, as well as the react and react-dom libraries. Let's get those to begin with by running the following sequence.

npm dependency installation

  npm install --save fetch@1.1.0
  npm install --save react@15.4.1
  npm install --save react-dom@15.4.1

The npm dependency installation syntax is npm install --save <package>@<version>. In this case, notice the packages and their versions are exactly the same as those used in the examples from part I.

It's worth mentioning you can omit the version syntax (e.g. npm install --save fetch) in which case npm installs the most recent package version. The --save flag is used to tell npm to update the package.json file with the installed package, which is helpful if you take or share your project elsewhere.

When you run the three npm install tasks from this last list you will see the result of the outcome on the screen. If it's successful the following happens:

We're almost done with dependencies. In addition to the last packages, remember the examples in part I also relied on the Babel package to transpile the React JSX component into JavaScript directly on a user's browser. Since we're now going to build the project before it hits any browser, let's install the Babel package dependency, as well as the Webpack bundler package and some other packages to achieve the build process.

npm development dependency installation

  npm install --save-dev webpack@2.1.0-beta.19
  npm install --save-dev webpack-dev-server@2.1.0-beta.9
  npm install --save-dev babel-core@6.21.0
  npm install --save-dev babel-loader@6.2.10
  npm install --save-dev babel-preset-react@6.16.0
  npm install --save-dev extract-text-webpack-plugin@2.0.0-beta.4
  npm install --save-dev style-loader@0.13.1
  npm install --save-dev css-loader@0.26.1
  npm install --save-dev html-webpack-plugin@2.24.1

I'll get to the purpose of each JavaScript package in the upcoming sections. The most important thing about this last dependency installation process is the --save-dev flag, which is used to save the package as a project development dependency [4]. Similar to the npm --save flag, the --save-dev flag saves packages to the packages.json file in a dedicated devDependencies section.

Next, let's perform a quick test so you understand the basic purpose of npm. Copy the package.json file in this project to a completely new folder. Placed in this new folder invoke the npm install command, this triggers the installation of all project dependencies once again and npm creates a new node_modules folder with all project packages. So by using an npm package.json file, you can easily share or restart a project without having to move around the full packages.

Now that you have a basic understanding of the npm package manager and where it places files, let's move on to the next step which involves using a bundler, in this case we will use the Webpack bundler [5].

Webpack bundler

If you look over the dependencies installed with npm, you'll see there's both a webpack and webpack-dev-server package, the first one contains webpack's core, while the second is a webpack utility to quickly test applications. Npm already installed the executables for both these packages, so there's no further action needed. Let's test the webpack executable located inside the webpack/bin folder in node_modules.

Webpack executable default output

  ./node_modules/webpack/bin/webpack.js

  No configuration file found and no output filename configured via CLI option.
A configuration file could be named 'webpack.config.js' in the current directory.
Use --help to display the CLI options.

In this case we use the relative path to access the webpack executable, but you can easily add this route as an executable path to your OS to access it automatically. Notice the output message says it can't find a webpack configuration file. Create a file called webpack.config.js -- note the .js extension for JavaScript -- and place it alongside the npm package.json file and node_modules folder. The next listing illustrates the contents of webpack.config.js required to replicate the examples from part I using webpack.

Webpack configuration for React/babel transpilation, CSS and HTML bundling.

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

module.exports = {
  entry: {
	'main':'./src/main.js'
  },
  output: { path: __dirname + '/build/',
	    filename: 'main.js' },
  module: {
    loaders: [
      {
        test: /.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query: {
          presets: ['react']
        }
      },
	{
            test: /\.css$/,
            loader: ExtractTextPlugin.extract({
                fallbackLoader: "style-loader",
                loader: "css-loader"
            })
	}
    ]
  },
    plugins: [
        new ExtractTextPlugin("styles.css"),
        new HtmlWebpackPlugin({template: "src/index.html"})
	new webpack.optimize.OccurrenceOrderPlugin(),
	new webpack.DefinePlugin({
	    'process.env': {
		'NODE_ENV': JSON.stringify('production')
	    }
	}),
	new webpack.optimize.UglifyJsPlugin({
	    compressor: {
		warnings: false
	    }
	})
    ]
};

Let's break down the explanation of this webpack configuration into five parts:

Now that you have a webpack configuration file ready to transpile and bundle your project files, as well as npm equipped with all project dependencies, let's take a look at the project's folder structure.

React project layout for npm/webpack

The following listing illustrates a React project folder and file structure for use with npm/webpack, elements in bold represent new folders/files I'll describe shortly.

React Project folder & file layout for npm/webpack

  +--node_modules (npm dependency folder)
  |
  +--package.json (npm configuration)
  |
  +--webpack.config.js (webpack configuration)
  |
  +--build (Final bundle location)
  |
  +--src--+
          |
          +-main.js (Webpack JS entry point)
          |
          +-index.html (Main HTML template)
          |
          +--app--+
          |       |      
          |       +-banner.jsx (JSX components)
          |
          |--assets--+
                     |
                     +--css--+
                             |
                             +-style.css (CSS file)

As you can see, there are a total of four new files. Just like in part I, a React project built with npm/webpack can be either based on pre-ES6 constructs or ES6, so I'll also create two sub-sections to describe both approaches. But before I do that, I'll describe the contents of the style.css and index.html files which don't change irrespective of using ES6 or pre-ES6 syntax.

The style.css file contains a simple CSS class used by a React component.

CSS style.css file

.hidden {
      display: none;
    }

The index.html file is used as a template to generate an HTML web page that references all the webpack bundled resources.

React index.html file

<!DOCTYPE html>
<html>
  <head>
    <title>React 101! built with npm & webpack - Modern JS</title>
    <meta charset="UTF-8" />
  <body>
    <div id="banner-container"></div>
  </body>
</html>

As you can see, this HTML file contains the same <div id="banner-container"></div> element used in the examples from part I, which loads the React component on the web page. But notice in this case there's no trace of JavaScript or CSS resources! so what's happening ? This last file isn't the web page that's sent out to end users, but rather a template that's used to generate the final web page. When you trigger the webpack build process, webpack uses this file and adds references that point to whatever bundles (JS & CSS) it creates. This template functionality is provided by webpack's Html Webpack plugin which you installed with npm and declared in the webpack.config.js file.

React & webpack pre-ES6 syntax

Now let's explore the files associated with a project that uses pre-ES6 syntax.

First let's take a look at the webpack entry file named main.js, the following snippet shows its contents

Webpack entry main.js file

require("./assets/css/style.css");
require("./app/banner.jsx");

It doesn't get much simpler than this file which uses require statements -- CommonJS syntax -- to tell webpack to load the contents from the ./assets/css/style.css and ./app/banner.jsx modules/files.

Now let's explore the banner.jsx file that contains the React components and whose contents are almost identical to the pre-ES6 exercise from part I.

React banner.jsx file

var React = require('react');
var ReactDOM = require('react-dom');

// Same contents between <script type="text/babel"> and </script> in pre-ES6 example 

You already created React components using the pre-ES6 ad-hoc API in part I, so the banners.jsx file contains exactly the same components, which correspond to the contents between <script type="text/babel"> and </script> in the pre-ES6 example. However, there's a notable difference in how both examples gain access to the React libraries. In this case the file uses the require statement to gain access to both the react and react-dom modules, where as in the example from part I the web page uses a <script> tag to load these same libraries that generate the React components.

There's not much more to add about this file since its React components were already described in part I. Webpack along with Babel are charged with transpiling and bundling the contents of this file when you execute the build process.

Now let's take a look at the ES6 version of this same React/Webpack project.

React & webpack ES6 syntax and requirements

The first thing you need to do to use ES6 in a React/Webpack project is install the corresponding dependency in npm to be able to transpile ES6. Run the following command npm install --save-dev babel-preset-es2015 -- note ES2015 is the same as ES6, the 2015 refers to the ECMAScript release year and the 6 refers to the ECMAScript version. This adds the ES2015(ES6) module to node_modules and updates npm's package.json to reflect this new package in the devDependencies section.

Next, you need to update the webpack webpack.config.js configuration file so it also expects to process ES6. The following snippet highlights the update you need to make to the webpack.config.js configuration file presented earlier.

Webpack configuration for React/babel transpilation updated with ES6 support


  module: {
    loaders: [
      {
        test: /.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query: {
            presets: ['react','es2015']
        }
  },

Notice the additional es2015 value for the presets list in the loaders query section.

Now let's update the remaining React project files to use ES6. The following listing illustrates the main.js updated to ES6.

Webpack entry main.js file using ES6

import * as Style from "./assets/css/style.css";
import * as Banner from "./app/banner.jsx";

Notice the file now uses the ES6 import keyword, instead of the require keyword which is part of CommonJS. As noted earlier in Modules, namespaces & module types, ES6 modules are the emerging standard but are still not mainstream.

Next, let's look at the actual React components using ES6 classes.

React banner.jsx file using ES6

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

// Same contents between <script type="text/babel"> and </script> in ES6 example 

Since you already created React components using ES6 classes in part I, the banners.jsx file contains exactly the same components, which correspond to the contents between <script type="text/babel"> and </script> in the ES6 example. However, there's a notable difference in how both examples gain access to the React libraries. In this case the file uses the import keyword -- part of ES6 -- to gain access to both the react and react-dom modules, where as the example from part I uses a <script> tag to load these same libraries that generate the React components.

Now that you've seen all the necessary details about this new React/Webpack project, it's time to build it and run it.

Build and run React webpack projects

All the heavy lifting has been done in the configuration files and the main project files. Now run the webpack executable alongside the webpack.config.js configuration. After you run the webpack executable, you'll see the results of the build process.

Webpack executable to build project

 ./node_modules/webpack/bin/webpack.js
    
  Version: webpack 2.1.0-beta.28
Time: 16155ms
     Asset       Size  Chunks           Chunk Names
   main.js     143 kB  0[emitted]  main
styles.css   36 bytes  0[emitted]  main
index.html  301 bytes  [emitted]  

Per the webpack configuration, the results of the build process are placed in the build folder. If you go to the build folder you'll see three files: main.js which bundles all the necessary JavaScript to run the project, styles.css which bundles all the CSS that belongs to the project and an index.html file -- based on the index.html template -- with references to the main.js and styles.css files.

Finally, run the webpack-dev-server.js executable to start a web server to test application using the following snippet

Webpack dev server to test application

  ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --content-base ./build

Notice the webpack dev server uses the --content-base flag to load its root directory on the build folder. Next, open a browser and point it to localhost:8080 to see identical React applications as the ones you did in part I, the difference is these last examples bundle every JavaScript dependency and the React component transpilation process is performed beforehand.