Setup React with webpack 3, babel and NPM

A few years ago jQuery was the best practice for Javascript/frontend development. Getting started with jQuery was as simple as creating an index.html document, include jQuery and start writing code.

Today, the frontend ecosystem has evolved. To get started with React you have to learn and configure NPM, webpack, babel AND React.

It is overwhelming to have to learn that many new technologies at once. And when talking to people and reading about webpack/babel, you get the impression it’s difficult.

I want to show you that it is not as complicated as it seems at first. Try out this tutorial step by step to see for yourself!

What we are going to do

We are going to set up a simple React project from scratch using the following tools:

  • webpack 3 for building
  • babel for transpiling React and ES6
  • npm for running the app and dependency management

Even tough our setup is simple it is going to be a production-ready setup.

What about CRA?

You have probably heard of create-react-app (CRA) which is an official tool to start a new React project. The recommended way to get started for newbies is to use CRA, but there are many reason to set up your own build setup with webpack/babel/NPM:

  1. CRA supports ejecting, which gives you a generated webpack config that you can edit. It is well documented but can be a pretty tough start to learn webpack anyway. For me personally, I learn best to code things from scratch!
  2. The underlying technologies of CRA are webpack/babel/NPM. To master React you want to know how it works under the hood.
  3. CRA does not support building an app with more advanced features such as server side rendering. You need to either “eject” from CRA, or set up the project from scratch.

Set up a new NPM project

Let’s start by creating a new NPM project:

mkdir react-starter
cd react-starter
npm init

npm init  will ask you a bunch of questions. Just press enter for the defaults. If you want, you can later change the config it generates by editing package.json that is created by this command.

Create a JavaScript source code file

Next, we are going to create our minimal React app and HTML file.

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

class HelloMessage extends React.Component {
  render() {
    return <div>Hello {}</div>;

var mountNode = document.getElementById("app");
ReactDOM.render(<HelloMessage name="Jane" />, mountNode);



<!DOCTYPE html>
        <title>React starter app</title>
        <div id="app"></div>
        <script src="bundle.js"></script>


We have created two directories: src  and dist.

  • src is the directory will contain our source files
  • dist is the directory we will configure webpack to put the compiled JavaScript files. To keep things simple, we put the index.html file straight in the dist folder because it’s static and don’t need to go through webpack.

Create the webpack 3 config file

Our webpack config file looks like this:

const webpack = require('webpack');
const path = require('path');

const config = {
    entry: './src/app.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    module: {
        rules: [
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: 'babel-loader'
module.exports = config;


It contains the following:

  1. The file src/app.js that we created previously is the entry point
  2. The file dist/bundle.js is the output file.
  3. The module section describes how webpack should transpile the code. It uses the babel-loader for all files that has a .js or a .jsx extension. In the next step we will configure babel-loader.

Add babel config

Babel is a highly configurable tool to transpile JavaScript. We are going to use a subset of babels features: transpiling ES6 and React JSX.

Our webpack config uses babel-loader to run babel which uses the regular babel config file.

We configure babel like this in the file .babelrc:

  "presets": ["es2015", "react"]


Now we have all the files we need

This is an overview of the files and folders we have created:

├── package.json
├── dist
│   └── index.html
├── src
│   └── app.js
└── webpack.config.js

2 directories, 4 files

Add dependencies

Before we run the application we must add NPM dependencies:

npm install --save-dev webpack
npm install --save-dev babel-loader
npm install --save-dev babel-core
npm install --save-dev babel-preset-es2015
npm install --save-dev babel-preset-react
npm install --save react
npm install --save react-dom

Our dependencies are now installed and our package.json file is updated with dependency information.

Run it

We are going to use NPM to start the build with webpack. Add this to the script area in package.json:

  "scripts": {
    "dist": "webpack -p"

Let’s run it and see what happens:

npm run dist

It works!

Now open up the file index.html in your browser. If you are on a mac, you can do it with this command: open dist/index.html

Now we see “Hello, Jane” in the browser. It is rendered through React and built with webpack/babel! It feels good to have 100% control on how the app is built!

What’s next

Run the code on your machine, and use that as your starting point for continuing your React journey. Tired of copy/pasting? Get the full code for this tutorial by subscribing below.

  • Hi, I’m snow. Few days ago I received your email, sorry I’m too busy recently. I like all of your frontend articles, 😀

    • jakoblind

      Hi Snow! Glad you still like my articles 🙂

  • Vijay Pawar


  • cnc

    Appreciate the article.

    What if you’re happy with using the create-react-app config, but then, there’s a major React update, such as the recent React 16.
    I have a React app in progress, but it was created with CRA way before 16. Seems like a hassle to try to update it now, and I’m not even sure how to do that, with the CRA config.

    Is it worth it to just scrap CRA permanently, and just start a new project, creating a build using your steps here, just to have the easier ability to update to future React updates?

    Seems like it would be ( and I might as well teach myself the various tools behind loaders, npm, babel, etc.. instead of staying on Training Wheels of cra )

    • jakoblind

      There are limitations with CRA, as you have just discovered. Therefor there is absolutely value in learning webpack, babel,etc to be able to build it yourself. CRA is great for some usecases, but for more critical applications it might not be the best choice.

      Is it worth scrapping your CRA and start a new project? I think only you can answer it 🙂 What I can say is that I agree with your reflections, and it is worth considering.

      If you want, please share what you decide to do and how it turns out! Good luck!

      • cnc

        Thank you, I’m in the middle of collecting a list of 3 or 4 articles like this, to compare and to see what modules you all have in common that are you using. Then when I have a weekend free, going full-force ahead to convert.

        • jakoblind

          That sounds like a solid approach. Good luck with your weekend hacking!