DEV Community

Cover image for How to setup Webpack and Babel for React
Ismile Hossain
Ismile Hossain

Posted on • Updated on

How to setup Webpack and Babel for React

All of us have used CRA(create-react-app) when we worked with React. It's an awesome tool. It gives us just to focus on React by letting take care of the configuration. Today we are going to learn how to setup Webpack and Babel for our React app.

First, let's learn about Webpack and Babel.

✔Webpack:

Its a module bundler which lets us bundle our project files into a single file.

A module is a file that contains definitions - including variables and functions, that we can use once it is imported.

It requires a webpack.config.js file in the root folder. Where we tell our webpack how to work with our application by giving entry point information and also output information.

const path = require('path');

module.exports = {
  entry: './src/app.js', // relative path
  output: {
    path: path.join(__dirname, 'public'), // absolute path
    filename: 'bundle.js' // file name
  }
};

Enter fullscreen mode Exit fullscreen mode

The "entry" point is where does our application going to kick off and we set it by giving relative path value. And the output property tells webpack where to emit the outputs it creates and how to name those files. We have to give absolute path value in our output path properties.

✔Babel:

It's a JavaScript compiler. Babel on its own actually has no functionality. Yeah, its a compiler but it's not going to compile anything by default. We have to add various plugins and presets to add support to particular language features. You can check this out by visiting Babel website. In the babel website navigation bar section you will find Try It Out. Click on it and you will get a new window.
Alt Text
Where in the left side window you can write your code and in the right side window you will get your compiled code. Now let's write some JSX in the left side window.

const template = <p>Hello</p>;
Enter fullscreen mode Exit fullscreen mode

In the right-side window, you will get JavaScript understandable compiled code which is always run behind the scene in our React app. On the left side, you see some PRESETS options where some options are already been ticked. If you now untick react presets option you will see an error caused this react preset is responsible for converting our JSX syntax into JavaScript understandable code.

In our tutorial we are going to use two presets:

  1. @babel/preset-env :- Which helps babel to convert ES6, ES7 and ES8 code to ES5.
  2. @babel/preset-react :- Which Transforms JSX to JavaScript.

Getting Started:

Now we know a little bit about webpack and babel. Let's dive into our React setup.

  • Create directories with these commands:

mkdir react-setup-tutorial
cd react-setup-tutorial
mkdir public src
touch public/index.html src/app.js

In index.html file add the following code inside it.

  <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>React App</title>
      </head>

      <body>
        <div id="root"></div>

        <script src="./bundle.js"></script>
      </body>
    </html>
Enter fullscreen mode Exit fullscreen mode
  • Initialize the project by running:

npm init -y

Install Webpack & React:

npm install webpack webpack-cli --save-dev

We installed webpack-cli so that we can use webpack in the command line.

We already know that webpack needs webpack.config.js to file in the root of the project directory. So let's create webpack.config.js file with the following code inside it.

const path = require('path');

module.exports = {
  entry: './src/app.js',
  output: {
    path: path.join(__dirname, 'public'),
    filename: 'bundle.js'
  }
};

Enter fullscreen mode Exit fullscreen mode

Next, add the webpack command inside package.json:

"scripts": {
    "start": "webpack --mode=development",
    "build": "webpack --mode=production"
  }
Enter fullscreen mode Exit fullscreen mode

There are two modes in Webpack, development and production. Which we can set by --mode flag. Production mode produces optimize files which are ready for use in production.

  • Install React:

npm install react react-dom

Now import react and react-dom inside our app.js file and also add some react code.

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

const template = React.createElement('p', {}, 'Hello from react');

ReactDOM.render(template, document.getElementById('root'));
Enter fullscreen mode Exit fullscreen mode

Now use below command in your terminal and open your index.html file in your browser.

npm start

Your app is working well. But you have a question why didn't we use JSX. This time lets try with some JSX code in our app.js file.

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

const template = <p>Hello from react</p>;

ReactDOM.render(template, document.getElementById('root'));
Enter fullscreen mode Exit fullscreen mode

Now again run our previous command.

npm start

This time you will get an error. That's because we use JSX and JavaScript doesn't support JSX. So If we want to use JSX in our app we need to compile it. And we can do it by babel.

Install & Configure Babel:

npm install @babel/core @babel/preset-env @babel/preset-react babel-loader --save-dev

We already know about @babel/preset-env and @babel/preset-react. Now, what is @babel/core and babel-loader?

  1. @babel/core :- It allows us to run babel from tools like webpack.
  2. babel-loader :- Its a webpack plugin. It allows us to teach webpack how to run babel when webpack sees certain files.

Let's configure babel by creating a .babelrc file inside the root of the project directory with the following contents inside of it.

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

Enter fullscreen mode Exit fullscreen mode

This file will tell babel which presets to use for transpiling the code.

  • Now its time to teach webpack how to compile JSX into JavaScript code. To do that we need to use loader. A loader lets us customize the behavior of webpack when it loads a certain file. It's going to run certain files through babel. For that, we need to set up a loader in webpack.config.js file via the module property on our objects. module property needs an array of rules and a rule let us define how we want to use our loaders. Now we have one rule to take JSX and convert it into JavaScript with Babel.
const path = require('path');

module.exports = {
  entry: './src/app.js',
  output: {
    path: path.join(__dirname, 'public'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      }
    ]
  }
};

Enter fullscreen mode Exit fullscreen mode

Here we set one rule of the object where loader property tells which loader we want to use and we use babel-loader. test property for what files do we actually want to run this loader on and we want to run it on files that end up with .js. exclude property to exclude a set of files and we use /node_modules/ cause we don't want to run babel through those libraries. Now we can use JSX in our React. Let's run our app again.

npm start

This time we don't get any error. Open your index.html file in the browser and yeah it's working.

Configure Source Map:

Let's add some extra configuration settings in our webpack.config.js file.

const path = require('path');

module.exports = {
  entry: './src/app.js',
  output: {
    path: path.join(__dirname, 'public'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      }
    ]
  },
  devtool: 'cheap-module-eval-source-map'
};

Enter fullscreen mode Exit fullscreen mode

Here we setup Source map by using devtool property. It enhances our debugging process. Its use to display our original JavaScript while debugging, which is a lot easier to look at than a minified code.

Install DevServer:

Run this below command in the terminal.

npm install webpack-dev-server --save-dev

Add following code inside webpack.config.js file.

const path = require('path');

module.exports = {
  entry: './src/app.js',
  output: {
    path: path.join(__dirname, 'public'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      }
    ]
  },
  devtool: 'cheap-module-eval-source-map',
  // changed line
  devServer: {
    contentBase: path.join(__dirname, 'public')
  }
};

Enter fullscreen mode Exit fullscreen mode

Next add webpack-dev-server command inside package.json:

"scripts": {
    "start": "webpack --mode=development",
    "build": "webpack --mode=production",
    "dev-server": "webpack-dev-server"
  }
Enter fullscreen mode Exit fullscreen mode

Now run this command.

npm run dev-server

It's going to start the development server. And It gives us output where we can access it. Now we have integrated both tools into one, the dev server is our server and its also running webpack for us.
Alt Text
Now we can visit the highlighted URL and we will get our app.

Loading the Styles:

Let's create a new file and folder in the src directory.

Use the following command to create a file and folder.

mkdir src/styles
touch src/styles/styles.css

Now add the following styles inside styles.css file.

* {
  color: blue;
}

Enter fullscreen mode Exit fullscreen mode

To load our style.css file we need to set up new rules in webpack.config.js file.

Before that, we need to install some new loaders.

npm install css-loader style-loader --save-dev

  1. css-loader: Allows webpack to load our CSS assets.
  2. style-loader: Take CSS and adds it to the DOM by injecting a <style> tag.

Now add new rules in our webpack.config.js file.

const path = require('path');

module.exports = {
  entry: './src/app.js',
  output: {
    path: path.join(__dirname, 'public'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
      // New rules to load css
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  devtool: 'cheap-module-eval-source-map',
  devServer: {
    contentBase: path.join(__dirname, 'public')
  }
};

Enter fullscreen mode Exit fullscreen mode

import style.css inside our app.js file and run dev-server to see the effect.

import React from 'react';
import ReactDOM from 'react-dom';
import './styles/styles.css';

const template = <p>Hello from react</p>;

ReactDOM.render(template, document.getElementById('root'));
Enter fullscreen mode Exit fullscreen mode

If we want to use SCSS then we need to install sass-loader that would help webpack to compile sass to css. The sass-loader is dependent on another package node-sass.

npm install sass-loader node-sass --save-dev

Now configure webpack.config.js file again for SASS by chaining sass-loader with the css-loader and the style-loader.

const path = require('path');

module.exports = {
  entry: './src/app.js',
  output: {
    path: path.join(__dirname, 'public'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
      // Rules to load scss
      {
      // Some change here
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      }
    ]
  },
  devtool: 'cheap-module-eval-source-map',
  devServer: {
    contentBase: path.join(__dirname, 'public')
  }
};

Enter fullscreen mode Exit fullscreen mode

Now chnage our style.css file extension .css to .scss that is style.scss

Also change the css import in app.js to:

import './styles/styles.scss';
Enter fullscreen mode Exit fullscreen mode

And add the following style to see that our wepback is working correctly for SASS.

$brand-color: blue;

* {
  color: $brand-color;
}

Enter fullscreen mode Exit fullscreen mode

Now run dev-server again by using the following command.

npm run dev-server

And we configure our webpack for SASS.

That's it. Now we have configured Webpack and Babel for React that we can use to create our React projects. Thanks for reading and stay tuned.

Latest comments (29)

Collapse
 
pfalzergbr profile image
pfalzergbr

After a full afternoon of struggle, you just helped me setting this up in 5 minutes. Thank you :)

Collapse
 
iamismile profile image
Ismile Hossain

Welcome🙂

Collapse
 
lukasdoesdev profile image
Lukas Does Dev

Super helpful. Thanks!

Collapse
 
iamismile profile image
Ismile Hossain

Welcome 🙂

Collapse
 
rana_talha profile image
Rana Talha

sir..? can you help me please if possible.

Thread Thread
 
rana_talha profile image
Rana Talha
Thread Thread
 
iamismile profile image
Ismile Hossain

Sure. How can I help you?

Collapse
 
hgg profile image
HGG

Thanks, great help.

Collapse
 
iamismile profile image
Ismile Hossain

Welcome🙂

Collapse
 
codeurh24 profile image
codeurh24 ☠️

Great, thank you !

Collapse
 
iamismile profile image
Ismile Hossain

Welcome🙂

Collapse
 
muhiddingithub profile image
Muhiddin Jumaniyazov

Hot reload is working with running dev-server?

Collapse
 
iamismile profile image
Ismile Hossain

Yes. It works.

Collapse
 
mikehale profile image
Mike Hale

It's not mentioned above, but if you use the sass option you need to change the css import in app.js to:

import './styles/styles.scss'

Collapse
 
iamismile profile image
Ismile Hossain

Thanks🙂

Collapse
 
lordliquid profile image
Robert Cutright • Edited

Thanks for the helpful tutorial!

If you are doing this tutorial around time of this comment you may experience an error similar:

Error: Cannot find module 'webpack-cli/bin/config-yargs'
Require stack:

  • C:\Projects\react-setup-tutorial\node_modules\webpack-dev-server\bin\webpack-dev-server.js

My Working Solution:

In your 'package.json' -

change:
"dev-server": "webpack-dev-server"

to:
"dev-server": "webpack serve"

Thread Thread
 
iamismile profile image
Ismile Hossain

Thank you🙂

Collapse
 
devsoonote profile image
Soo

Thank you a lot! :-)

Collapse
 
iamismile profile image
Ismile Hossain

Welcome🙂

Collapse
 
bludnic profile image
bludnic

Typo in two places:
cheap-module-eavl-source-map => cheap-module-eval-source-map

Collapse
 
iamismile profile image
Ismile Hossain

Thanks for noticing🙂

Collapse
 
vanevo00 profile image
Vojtech

Very helpful thanks!

Collapse
 
iamismile profile image
Ismile Hossain

Welcome🙂

Collapse
 
ablaabiyad profile image
ablaabiyad

Thanks a lot Ismile.

I had to register in github then here, so I can write this comment.
I hope this will be my beginning :)

Collapse
 
iamismile profile image
Ismile Hossain

Welcome🙂
And All the Best for You.

Collapse
 
ivan_jrmc profile image
Ivan Jeremic • Edited

The easiest tutorial to follow I have ever seen! Every tutorial made on the earth should be structured like this one! Thank you so much!

Collapse
 
iamismile profile image
Ismile Hossain

Welcome🙂

Collapse
 
msdorachua profile image
Dora Chua

Thanks so much, your tutorial was easy to follow and works flawlessly! Good job! :)

Collapse
 
iamismile profile image
Ismile Hossain

Welcome🙂. Thanks to you also for appreciating my work.