Tutorial: How to set up React, webpack 4, and Babel (2018)

React is mostly used for Single Page Applications.

Yet it’s possible to integrate the library into any website with webpack and Babel.

How to set up React, webpack 4, and Babel (2018)

How to set up React, Webpack, and Babel: what you will learn

  1. how to install and configure webpack
  2. how to install and configure Babel
  3. how to install React
  4. how to create two React components by following the Container / Presentational principle
  5. how to include the resulting bundle into an HTML page
  6. how to install and configure Webpack Dev Server

React is not limited to full blown SPA. It’s possible to integrate the library into any existing website.

React can be pulled in either with a CDN or with a module bundler.

For most of my projects I use Webpack: combining React and webpack is easy as a breeze.

You can do the same and have a working webpack 4 – React environment in minutes: here is a short tutorial for you.

How to set up React, webpack, and Babel: setting up the project

Start off by creating a directory for the project:

mkdir webpack-react-tutorial && cd webpack-react-tutorial

Create a minimal directory structure for holding the code:

mkdir -p src

Inizialize the project by running:

npm init -y

and you’re good to go.

How to set up React, webpack, and Babel: setting up webpack

webpack is one of the pillars of modern Web Development. It’s an incredibly powerful tool.

Knowing how to use webpack is fundamental for working with React.

webpack ingests raw React components for producing Javascript code that (almost) every browser can understand.

Let’s install it by running:

npm i webpack --save-dev

You will also need webpack-cli. Pull it in with:

npm i webpack-cli --save-dev

Next up add the webpackcommand inside package.json:

"scripts": {
  "build": "webpack --mode production"

At this point there is no need to define a configuration file for webpack.

Older webpack’s version did automatically look for a configuration file.

Since version 4 that is no longer the case: you can start developing straigh away.

In the next section we’ll install and configure Babel for transpiling our code.

How to set up React, webpack, and Babel: setting up Babel

React components are mostly written in Javascript ES6.

Since the browser can’t understand React components as they come there is the need for some kind of transformation.

Webpack doesn’t know how to make the transformation but it has this concept of loaders: think of them as of transformers.

A Webpack loader takes something as the input and produces something else as the output.

babel-loader is the Webpack loader responsible for taking in the ES6 code and making it understandable by the browser of choice.

Obsviusly babel-loadermakes use of Babel. And Babel must be configured to use a bunch of presets:

  1. babel-preset-env for compiling Javascript ES6 code down to ES5 (please note that babel-preset-es2015 is now deprecated)
  2. babel-preset-react for compiling JSX and other stuff down to Javascript

Let’s pull in the dependencies with:

npm i babel-loader babel-core babel-preset-env babel-preset-react --save-dev

Don’t forget to configure Babel! Create a new file named .babelrcinside the project folder:

  "presets": ["env", "react"]

At this point we’re ready to define a minimal webpack configuration.

Create a file named webpack.config.jsand fill it like the following:

module.exports = {
  module: {
    rules: [
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"

The configuration is quite simple.

For every file with a .jsextension Webpack pipes the code through babel-loader for transforming ES6 down to ES5.

With this in place we’re ready to write our React components.

Let’s head over the next section.

How to set up React, webpack, and Babel: writing React components

I like writing my React components by following the Container / Presentational principle.

I suggest taking a look at container components and smart and dumb components by Dan Abramov for learning more.

In brief, the Container / Presentational principle is a pattern for React components.

The container component is the one that carries all the logic: functions for handling state changes, internal component state and so on.

In contrast a presentational component is merely used for displaying the desired markup. Presentational components are usually plain arrow functions and receive data from the container component as props.

You’ll see how they look like in the following example.

For this post’s scope I’d like to build a super simple React form with a single text input.

Before touching any code let’s pull in React by running:

npm i react react-dom --save-dev

Then create a minimal directory structure for organizing the components:

mkdir -p src/js/components/{container,presentational}

Next up let’s create a container component that:

  • has its own state
  • renders an HTML form

Create the component into src/js/components/container/:

touch src/js/components/container/FormContainer.js

The component will look like the following:

import React, { Component } from "react";
import ReactDOM from "react-dom";

class FormContainer extends Component {
  constructor() {

    this.state = {
      title: ""

  render() {
    return (
      <form id="article-form">

export default FormContainer;

The component does nothing at this moment. It’s just a skeleton for wrapping up child components.

In fact a container component without its presentational child is almost useless.

Let’s fix that.

Create a new component inside src/js/components/presentational/:

touch src/js/components/presentational/Input.js

Our first presentational React component will be a text input. We know that an HTML input takes the following attributes:

  • type
  • class
  • id
  • value
  • required

All of these will become props that the container component will pass down to its presentational child.

Since the input holds its own state we must be sure that React will take care of it. An HTML input becomes a controlled component in React.

Speaking of props, it is good practice to document your React components with Prop Types.

Install the package by running:

npm i prop-types --save-dev

Back to React, our presentational component for an HTML input will look like the following:

import React from "react";
import PropTypes from "prop-types";

const Input = ({ label, text, type, id, value, handleChange }) => (
  <div className="form-group">
    <label htmlFor={label}>{text}</label>

Input.propTypes = {
  label: PropTypes.string.isRequired,
  text: PropTypes.string.isRequired,
  type: PropTypes.string.isRequired,
  id: PropTypes.string.isRequired,
  value: PropTypes.string.isRequired,
  handleChange: PropTypes.func.isRequired

export default Input;

At this point we’re ready to update our container component to include the text input:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import Input from "../presentational/Input";

class FormContainer extends Component {
  constructor() {

    this.state = {
      seo_title: ""

    this.handleChange = this.handleChange.bind(this);

  handleChange(event) {
    this.setState({ [event.target.id]: event.target.value });

  render() {
    const { seo_title } = this.state;
    return (
      <form id="article-form">
          text="SEO title"

export default FormContainer;

Time to wire things up.

Webpack expects the entry point to be ./src/index.js

Create ./src/index.jsand place an import directive into it for requiring the container component:

import FormContainer from "./js/components/container/FormContainer";

With this in place we’re ready to create our bundle by running:

npm run build

Give Webpack a second and see the bundle come to life!

The bundle will be placed into


Now let’s bring our React experiment to life by including the bundle into an HTML page.

How to set up React, webpack, and Babel: the HTML webpack plugin

To display our React form we must tell Webpack to produce an HTML page. The resulting bundle will be placed inside a <script></script>tag.

Webpacks needs two additional components for processing HTML: html-webpack-plugin and html-loader.

Add the dependencies with:

npm i html-webpack-plugin html-loader --save-dev

Then update the webpack configuration:

const HtmlWebPackPlugin = require("html-webpack-plugin");

module.exports = {
  module: {
    rules: [
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        test: /\.html$/,
        use: [
            loader: "html-loader"
  plugins: [
    new HtmlWebPackPlugin({
      template: "./src/index.html",
      filename: "./index.html"

Next up reate an HTML file into ./src/index.html(feel free to use whichever CSS library you like):

<!DOCTYPE html>
<html lang="en">

    <meta charset="utf-8">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" >
    <title>How to set up React, Webpack, and Babel</title>

    <div class="container">
        <div class="row mt-5">
            <div class="col-md-4 offset-md-1">
                <p>Create a new article</p>
                <div id="create-article-form">
                    <!-- form -->




One last thing is missing! We must tell our React component to hook itself into <div id="create-article-form"></div>.

Open up ./src/js/components/container/FormContainer.jsand add the following at the bottom of the file:

const wrapper = document.getElementById("create-article-form");
wrapper ? ReactDOM.render(<FormContainer />, wrapper) : false;

Close and save the file.

Now run the build again with:

npm run build

and take a look at the ./distfolder. You should see the resulting HTML.

With webpack there’s no need to include your Javascript inside the HTML file: the bundle will be automatically injected into the page.

Open up ./dist/index.htmlin your browser: you should see the React form.

How to set up React, webpack, and Babel: webpack dev server

You don’t want to type npm run buildevery time you change a file.

It takes only 3 lines of configuration to have a development server up and running.

Once configured webpack will launch your application inside a browser.

Also, every time you save a file after a modification webpack wev server will automagically refresh the browser’s window.

To set up webpack dev server install the package with:

npm i webpack-dev-server --save-dev


Open up package.jsonto add the start script:

"scripts": {
  "start": "webpack-dev-server --open --mode development",
  "build": "webpack"

save and close the file.

Now, by running:

npm start

you should see webpack launching your application inside the browser.

Webpack Dev Server

Webpack Dev Server will automagically refresh the window upon every modification to a file!

How to set up React, webpack, and Babel: wrapping up

React is mostly used for creating Single Page Applications. But it can also fit into any website.

By combining webpack and Babel it is possible to transform a bunch of React components into a bundle suitable for being distributed.

In the above guide we’ve seen:

  • how to install and configure webpack
  • how to install and configure Babel
  • how to install React
  • how to create two React components by following the Container / Presentational principle
  • how to include the resulting bundle into an HTML page
  • how to install and configure webpack dev server

By the end you should be able to start from scratch with React, webpack and Babel.

For learning more about webpack check out webpack 4 tutorial, from zero conf to production mode.

Thanks for reading!

Valentino Gagliardi

Valentino Gagliardi

Consultant, Developer Coach. Are you stuck on a project? Let's talk!
Valentino Gagliardi

62 Replies to “Tutorial: How to set up React, webpack 4, and Babel (2018)”

  1. Thank you for taking the time to put this together. The simplest example with links to a bunch of concepts was great. I’ve done much more complex tutorials, but found this to help better with understanding. Looking forward to doing your React Redux 2018 tutorial 🙂

    1. Andrew, thanks for stopping by! In short, no, when bundling with a module bundler you can safely put react and react-dom in devDependencies. Either way you’ll ship a single bundle containing all the dependencies imported through webpack.

  2. Hello, I want to say thank you for the tutorial! It helped me greatly to learn how it works. I’m looking forward for another tutorial from you.


  3. hi, thanks for the tutorial, im following some tutorial from several side and they configure it diferently, specially in using html -webpack-plugin. Some using it, some not, can you suggest me any reference when to use it? special thanks.

  4. Thank you, Valentino, for writing this tutorial! It was extremely helpful and to-the-point. One thing I was having an issue with was getting an error “webpack: command not found” and wanted anyone following along with this who may also have the issue is to try using the path to webpack, like so:

    “build”: “./node_modules/.bin/webpack”

  5. This is the first React tutorial I’ve done that has actually worked. Not so much because the code was correct, but all these libraries are moving targets. The one extra thing I had to do was `$ npm install webpack-cli -D` at the end of the “Writing React Components” section – on the first run of `npm run build` I got an error:
    The CLI moved into a separate package: webpack-cli.
    Please install ‘webpack-cli’ in addition to webpack itself to use the CLI.
    -> When using npm: npm install webpack-cli -D
    … which was cleared up by installing the extra package.
    However, fantastic tutorial taking us through all the tools needed to get up and going.

  6. Finally a tutorial that actually works!!! Thanks for that! You made my day. I would really appreciate if you could help by writing something on how to implement CSS Modules with the above setup.

  7. Excellent tutorial. Let me ask you some questions. How to complete your project by publishing components on NPM? What are the best practices of placing components on a site (not a SPA)? What would you advise a newcomer – to learn CRA or NWB or experiment with your project?

  8. Really helpful and well explained. I am a total beginner on React development, and now I can start my journey from a solid ground. Thanks a lot.

  9. Hi,

    How do I install the Contrib version for HtmlWebPackPlugin,
    I tried npm install git://github.com/jantimon/html-webpack-plugin.git –save
    but I guess I’m missing something.

    Please help thanks,

  10. Can you help me?

    First, thank for your post.

    Today i try use arrow function and receive this error

    Module build failed: SyntaxError: C:/Users/hiarlay.rolim/Documents/projetos/esocial/desenvolvimento/sepog-react-template/src/js/components/presentational/Menu.js: Unexpected token (11:17)

    9 | }
    10 |
    > 11 | evtAbrirMenu = () => {
    | ^
    12 | alert(‘teste’)
    13 | }

    Do you have any idea?
    I search but only find with preset preset-es2015

  11. Great tutorial. However, after running npm run build, I see :

    Child html-webpack-plugin for “index.html”:
    1 asset
    Entrypoint undefined = ./index.html

    And I notice the form is not rendered into index.html at the target location:

  12. Valentino, there’re almost tree articles about webpack 4 and almost about the same….which one should I start with? I have React exercises from ’17 with the need of sass, babel, dev-server so it’s like here but I almost feel lost jumping from one to other article….it’s like about the same or some other points are stressed and explained?

  13. Thank you very much. I tried many previous tutorial and blog to install webpack but failed each time. After two days of trying, I began to lose hope. I followed several guideline from stack overflow but none of them solve my problem in 2018. I am a very beginner so I am at a loss to decide what to do now. At last, luckily I found your blog and install Webpack successfully. Thank you once again for you time and sharing knowledge with us.

  14. I tried to setup webpack.output.path along with HtmlWebPackPlugin. I get Entrypoint undefined. it is only happening when i use path variable defined. HtmlWebPackPlugin always set patj as dist/js src attribute. But not using output.path.

    I added “–content-base src/” while running the build. Still get the error. But at least js file path is set properly in src.

    Hope this helps others. If you know any other straight forward solution, please let us know. 🙂

    Tutorial is awesome..!!!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.