How To Create A React App From Scratch Using Webpack 5 + Babel

How To Create A React App From Scratch Using Webpack 5 + Babel

ยท

6 min read

The easiest way of creating a react application is using a create-react-app tool. This is good to use when you have just started learning React but it hides a lot of details regarding:

  • What happens under the hood
  • What configuration is needed to work with the latest features
  • How does the conversion from ES6 to ES5 happen

Also, when working on an industry/company project, most of the time, you will need to use custom webpack configuration instead of create-react-app.

So, in this article, we will set up webpack 5 + Babel in React from scratch.

So without wasting much time, let's start with the configuration.

  • Create a new folder with the name react_webpack_setup (You can name anything you wish).
mkdir react_webpack_setup
  • Create a package.json file inside the react_webpack_setup folder by running the following command in terminal
cd react_webpack_setup
npm init -y
  • Install babel and the plugins required for using babel by running the following command:
npm install @babel/core@7.15.0 @babel/preset-env@7.15.0 @babel/preset-react@7.14.5

Let's understand what these packages do.

@babel/core - It provides basic core babel configuration

@babel/preset-env - It allows to work with the latest ES6/ES7/ES8 features

@babel/preset-react - It allows to work with React syntax which is JSX

  • Create a new folder with the name public and create a new file index.html inside it with the following content:
<!DOCTYPE html>
<html lang="en">
<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 Webpack Setup</title>
</head>
<body>
    <div id="root"></div>
</body>
</html>
  • Create a new folder src outside the public folder and a new file with the name index.js inside it

  • Create a new file with the name webpack.config.js inside the react_webpack_setup folder and add the following content inside it:

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

Here we are telling webpack, what is the entry point of the application and to put the generated output file bundle.js inside the public folder.

This is how your folder structure will look now:

file_structure.png

  • Now install the webpack, webpack-cli and webpack-dev-server(which is used to serve the public directory and reload the changes in the browser when we make any change in the code).

Execute the following command to install it:

npm install webpack@5.51.1 webpack-cli@4.8.0 webpack-dev-server@4.0.0
  • Now to install react, react-dom and babel-loader, run the following command in the terminal:
npm install react@17.0.2 react-dom@17.0.2 babel-loader@8.2.2
  • Now we will set up the babel-loader which will convert your ES6 and React code to ES5.

Add the following code in webpack.config.js after the output property:

module: {
  rules: [{
    loader: 'babel-loader',
    test: /\.js$/,
    exclude: /node_modules/
  }]
},

Here we are telling babel-loader to look for only .js files to convert to ES5 code but exclude the .js files from the node_modules folder.

Now your webpack.config.js file will look like this:

const path = require('path');
module.exports = {
    entry: './src/index.js',
    output: {
            filename: 'bundle.js',
            path: path.join(__dirname, 'public')
    },
    module: {
            rules: [{
                loader: 'babel-loader',
                test: /\.js$/,
                exclude: /node_modules/
            }]
    }
};
  • Now create a new file with the name .babelrc (Note the file name starts with a dot) and add the following content inside it:
{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ]
}

This file will tell the babel-loader to use env and react presets (which are just plugins) when converting ES6 to ES5.

We are all done with the setup now.

Letโ€™s write some React code to check the application.

Add the following content in the index.js file which is inside the src folder:

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

class App extends React.Component {
  render() {
    return (
      <h1>Welcome to REACT</h1>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
  • Now to run the application, we need to make two changes:

a) Include the bundle.js file which will be generated by webpack in the index.html file

Add the following line in public/index.html after the div tag:

<script src="bundle.js"></script>

So the final public/index.html will look like this now:

<!DOCTYPE html>
<html lang="en">
<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 Webpack Setup</title>
</head>
<body>
    <div id="root"></div>
    <script src="bundle.js"></script>
</body>
</html>

b) Add the following two scripts to the package.json file. ( Replace the old script's entry)

"scripts": {
 "build": "webpack",
 "start": "webpack serve"
}

So your package.json file will look like this now:

{
  "name": "react_webpack_setup",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack",
    "start": "webpack serve"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@babel/core": "^7.15.0",
    "@babel/preset-env": "^7.15.0",
    "@babel/preset-react": "^7.14.5",
    "babel-loader": "^8.2.2",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "webpack": "^5.51.1",
    "webpack-cli": "^4.8.0",
    "webpack-dev-server": "^4.0.0"
  }
}
  • Now to inform webpack that it should run in development mode (default is production mode) to speed up the build process, add the following line in webpack.config.js file:
mode: 'development'
  • Now, the final webpack.config.js file will look like this:
const path = require('path');
module.exports = {
    entry: './src/index.js',
    output: {
            filename: 'bundle.js',
            path: path.join(__dirname, 'public')
    },
    module: {
            rules: [{
                loader: 'babel-loader',
                test: /\.js$/,
                exclude: /node_modules/
            }]
    },
    mode: 'development'
};
  • To run the application, execute the following command from the terminal:
npm start

welcome.png

Now, try making any change in index.js like changing "Welcome to REACT" to "Welcome to REACT!" and save it.

Now you will see that webpack-dev-server will automatically restart your application and you will see the changes reflected in the browser.

Note: webpack-dev-server will serve the bundle.js directly from memory and will not create a local file inside the public folder to speed up the page loading.

You can manually create the bundle.js if required by executing the following command

npm run build

Note that, we have already added the build script in the package.json file.

Thanks for reading!

You can find GitHub source code for this article in this repository.

Check out my recently published Mastering Redux course.

In this course, you will build 3 apps along with food ordering app and you'll learn:

  • Basic and advanced Redux
  • How to manage the complex state of array and objects
  • How to use multiple reducers to manage complex redux state
  • How to debug Redux application
  • How to use Redux in React using react-redux library to make your app reactive.
  • How to use redux-thunk library to handle async API calls and much more

and then finally we'll build a complete food ordering app from scratch with stripe integration for accepting payments and deploy it to the production.

Want to stay up to date with regular content regarding JavaScript, React, Node.js? Follow me on LinkedIn.

Did you find this article valuable?

Support Yogesh Chavan by becoming a sponsor. Any amount is appreciated!