Tutorial: How to set up React, webpack, and Babel 7 from scratch (2020)

Have you ever wondered how to set up React, webpack, and Babel from scratch? I’ve got you covered!

Tutorial: How to set up React, webpack, and Babel 7 from scratch

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

In this tutorial you’ll learn:

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

Enjoy the reading!

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 $_

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 it’s an incredibly powerful tool. While you can get by without touching a single line of configuration there will be a time for some custom setup of sort. Sooner or later you may want to learn webpack. Why not starting now?

Learning webpack is valuable not only for working with React but for configuring every frontend project.

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. ES6 is a nice improvement over the language but older browsers cannot understand the new syntax. Take the class keyword for example. Stateful React components are declared as classes (I guess it will be no longer the case sooner or later). So for getting ES6 to work in older browser we need some kind of transformation.

And that transformation is called transpiling. Webpack doesn’t know how to transform ES6 JavaScript to ES5 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-loader makes 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/core babel-loader @babel/preset-env @babel/preset-react --save-dev

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

  "presets": ["@babel/preset-env", "@babel/preset-react"]

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

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

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

The configuration is quite simple.

For every file with a js or jsx extension 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

Let’s start with the right foot: we’ll create two React components 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 intended markup. Presentational components are plain JavaScript functions receiving 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

A question I get a lot is “should I install react and react-dom as dev dependencies or not?” It doesn’t matter for the final result. webpack will still produce a bundle with your JavaScript application. I have this bad habit of putting react and react-dom in devDependencies so you’ll find that style a lot in my tutorials.

Next up 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:

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

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. Let’s fix that.

Create the new component:

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

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.jsx";

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;

And now it’s time to wire things up! webpack expects the entry point to be ./src/index.js. Create the file and place an import directive into it for requiring the container component:

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

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 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|jsx)$/,
        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 prefer):

<!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 the id create-article-form

Open up ./src/js/components/container/FormContainer.jsx and 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 ./dist folder. 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.html in 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 build every 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.json to add the start script:

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

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

create-react-app is the way to go for starting off a new React SPA project. Almost everything is configured out of the box. But sooner or later you may want to extend or tweak webpack a bit.

And if you learn how to set up React, webpack, and Babel by hand you’ll be able to scratch your own itch, or even configure a frontend project from zero.

This knowledge is also valuable for situations where you don’t need a full blown SPA but you still want to build and distributed your ES6 code. 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 with 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.

And if you want to challenge yourself check out my React Redux Tutorial for Beginners: it builds on this webpack/babel foundation.

Thanks for reading and stay tuned!

Need JavaScript training for your team?


184 Replies to “Tutorial: How to set up React, webpack, and Babel 7 from scratch (2020)”

    1. Thank you,

      Previously I only experienced using react with ‘create-react-app’. You have somehow managed to make the impossible achievable. For a struggling web developer like myself this tutorial put a big smile on my face. Fantastic!

  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. Thanks for the great tutorial! I have followed and got it working. By far the best minimal stater kit πŸ™‚

  15. 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..!!!

  16. Nice Tutorial πŸ˜€ Finally got the installation without error. but one question sir, if i make a new file for html and js.. where should i save it?

  17. Thanks very much!!

    Very clear explanined and with good examples!! Finally i can understand how to config a project from scratch!

  18. Nice post, but I can’t follow it, when I run “npm run build” I get this:
    Error: Plugin/Preset files are not allowed to export objects

  19. Thank’s for this post! I tried upgrading babel to 7 the day it came out, but the auto-updated didn’t touch the webpack config file, and I couldn’t get it to work. Today I did it in 10 minutes.

  20. Thank you so much. I have tried many tutorials to understand react coming from a Python background. You really killed this. The tutorial was clean, concise and even explain whys and hows of other things as well. Really love it.

    You helped me kickstart a long pending project of mine.

  21. As a beginner in React and production-level front-end development, this was the best article I found so far that actually explains how things “magically” work together.
    I had no idea what the ** web pack was before reading this article, for example.
    Great work!

  22. Thank you for the really clean explanation! Looking forward to more articles like these. BTW, I learned a new shortcut from this article πŸ˜‰

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

  23. Hello!
    Awesome write-up and code πŸ™‚ I use it constantly.

    Do you / anyone know what has to happen for react-router to work with this?
    Perhaps I’m missing something simple, but I’ve worked with react router in C-R-A, & I’m not sure why it’s not working for me with this react-wp-babel appreach πŸ™


  24. Many thanks for this article! With your clear instructions, I got a starter app going first time. I tried a couple of tutorials before yours on creating a skeleton React app, neither of which worked due to changes to babel and webpack making them out of date. Good job.

  25. super cool tutorial… helped me a lot, got me from nothing to actually being able to Google what I need!!

    You should have a post about production grade optimization and minification plugins.. this seems to be a too diverse topic.

  26. Very helpful update on the latest and greatest in webpack and babel. Than you!

    One suggestion:
    Include babel-plugin-transform-class-properties. This way you can modern syntax as in

    handleChange = (event) => {
    this.setState({ seo_title: event.target.value });

    and drop //this.handleChange = this.handleChange.bind(this);

  27. Valentino, thank you for very nice tutorials. I tightly followed the tutorial but I am getting the “Unexpected token” for jsx code. What might be the problem?

    1. Pete – I receive the same, I cross reference a couple of apps I have built with ‘create-react-app’ and the simple render method syntax looks correct to me. Its like its confused because its a native html tab or something.

      ERROR in ./src/js/components/container/FormContainer.js
      Module build failed (from ./node_modules/babel-loader/lib/index.js):
      SyntaxError: D:\Workspaces\webpack-react-tutorial\src\js\components\container\FormContainer.js: Unexpected token (12:6)

      10 | render() {
      11 | return (
      > 12 |
      | ^
      13 |
      14 | );
      15 | }

    2. Pete — I got past this, it appears it was not picking up my .babelrc file, the filename was the issue (windows explorer nerfed me) I opened a terminal to create the filename correctly and it worked as written.

  28. Do you have this on github?
    I followed the tutorial and I get a console error:

    Uncaught ReferenceError: require is not defined
    at eval (external_”url”:1)

  29. Thank you for a very well put together tutorial.
    For this to work with the latest version of React, the JSX of the Input component needs to be wrapped in a `return()`

  30. Before this tutorial ,It was really very difficult to understand Webpack and Babel , hats off to you tha way you explained .
    Thank you very much ,I become a fan of you !! >3 πŸ˜€ πŸ™‚

  31. I tried this with Create React App 2 (does anyone setup a React app without this?) and now everything errors. Sorry, didn’t work for me.

  32. Thanks for such a nicely explained and wonderful article with Step by Step. I am a novice in React and was struggling to set up the project. I was able to set up and run the project in first go.

  33. thank you for wasting my time.
    this tutorial is even ame buggy than the redux tutorial.

    great that guys like you give so good tutorials only the privy are able to understand because you do not share your swissen dominion.

  34. Thanks buddy, it fills the gap between and the stock React docos. As a React newbie, I know that eventually I will use create-react-app, but when you’re just starting, create-react-app got too much magic in it. Like, wtf is Babel and where it fits into the picture – your tutorial perfectly explains it.


  35. Hey Valentino,

    thanks for the tutorial, i have an error on my first “npm run build” : “Insufficient number of arguments or no entry found.”, do you (or anyone!) know what’s it about?

    Thanks again for the great work!

  36. Thank you so much! Such a great tutorial, really helped bring me up to speed on the basics of modern JavaScript web development!

  37. First of all, thanks for your tutorial, I assume it is really great, except till now I keep getting:

    ERROR in ./src/js/components/container/FormContainer.jsx 18:6
    Module parse failed: Unexpected token (18:6)
    You may need an appropriate loader to handle this file type.
    | const { seo_title } = this.state;
    | return (
    | <Input
    | text="SEO title"
    @ ./src/index.js 1:0-72

    Looks like Joe had a similar issue, nevertheless .babelrc exists on my mac. Anybody else, who faced a similar issue?

    1. Hello Joan,

      I know this reply is about 6 months due, but I thought I’d reply nonetheless, as it might also help someone in the future.

      I also ran into the exact same error, and it turns out I just placed the “webpack.config.js” and “.babelrc” files in the wrong directory. Both of these files should be at the root of your project folder, where the “src” and “node_modules” folders are.

      That’s all it took to get rid of the error for me, and as such I was able to successfully execute the “npm run build” command.

  38. Thanks. Very well written and comprehensive tutorial.
    I was looking around for a solution to have a webpack+babel configured.
    I have a project to handle multiple src directories and their own dist. I want to have unique repository to handle src and dist for some js extensions I need deploy (each code is independent but I wish to have all dist under a dir ./public/extension/{index.html, main.js} and having each source code under ./src/ext/{js/, index.html}

    Does it make sense to you? Do you have any recommendation to set up webpack to build these independently, with such dir structure?

  39. Nicely done, these steps worked right out of the box for me, saved me a ton of time trying to troubleshoot / upgrade from the older video I’d been working from. Thanks!

  40. Can you publish your code? Also, I think it’s not correct that FormContainer is not rendered inside index.js but only imported.

  41. Excellent guide.

    Through the changes react has gone through and with convoluted description on webpack and babel, lot of tutorials have became unhelpful or just too much. Your guide was fast and simple for newly starting basic react project.

  42. Hey man!

    First of all thanks for the tutorial.
    I have a question: why did you add react and react-dom as dev dependency?
    Can you elaborate on that?

    Many thanks πŸ™‚

    1. Hi! It’s just a bad habit of mine but in the end the result will still be a JavaScript bundle, it doesn’t matter if React is in the dev dependencies. But now that you pointed out let me fix it πŸ™‚

  43. Nicely explained…

    Big thing for junior / senior developer is to have one boiler plate first..

    & I think this article helps to go that way

  44. Thanks for making this so detailed and easy.

    However I am not able to enable source map with this development setup.
    I tried adding `devtool: “source-map”` in my webpack config file but this didn’t help.

  45. This article has something that so many are missing – in addition to *what* to do, you provide an explanation of *why* to do it. Very clear and helpful – thanks!

  46. For those of us that hate all the garbage that goes on behind the scenes when you create a project using npx coupled with the crippling decision of whether to eject or not…..THANK YOU!

    Brilliant stuff here.

  47. Thanks, after trying to move from create-react-app i came across a different article from another source where i got some issues with babel and webpack not finding lot of stuff, your article fixed these issues. Thank you.

  48. Excellent! There are very few examples like this which try to stick to the point w/o getting off topic too soon. And this is so up to date. A number of other examples out there are not kept up to date, but I understand how that is difficult in the world of Javascript. This helped me publish my first NPM package containing JSX. It’s private (proprietary) so I can’t show you πŸ™‚

    You might make it clear that the default entry point in the generated package.json is ./index.js not ./src/index.js which is what it must be changed to in order to succeed.

  49. After I install html-webpack-plugin, update my webpack conf and redefine my components, I then run the npm script. I get this error:

    ReferenceError: HtmlWebPackPlugin is not defined

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.