React Webpack 5 Setup - Understand everything you need to know
Tags: webdev, javascript, react, beginners
Published: 2024-01-12 14:22:58

I know there are so many articles you can find online.
What I am doing different here is I will explain the process and every line you write.

So, we will use latest React 18+ version and Webpack 5.

## Step 1: Creating Project Directory
Create an empty folder in your hard drive. Open it in your favorite editor. You can open integrated terminal or separate terminal.

![Create Folder](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/57hnrgnj32j97tdbb0r7.png)

## Step 2: Initialize project with NPM
`npm init --yes`
It will create a package.json file
We used '--yes' to pre-fill all the required things in package.json. You can update the details later.


## Step 3: Create source folder
lets create a folder 'src' to hold all the components
create two files index.js and App.jsx. 
I have used 'jsx', so that we know it is bundling jsx files as well.


![Index and app file creation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnbl6xqm4eq1mxou3ptr.png)

## Step 4: Create a index.html file
Create a 'public' folder in root directory, and create index.html file.
This will be our template that will mount our react components.
To mount our react root component, create a div with id 'root', although you can use any name.

![index.html](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oqgh6f760hb26bk5oeda.png)

## Step 5: Install react and react-dom
We are going to use 'react-dom/client' to create a root and mount our main component there.
To write jsx syntax, we need react.
`npm i -D react react-dom`

![index.js setup](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z93xnrci9tsofee47gv9.png)

## Step 6: Define our App component

![App component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dywhqafqtpt18y0mqvdt.png)
**Note - Don't forget to import it in index.js**

Although, we have written code for React but till now there is no way to compile jsx syntax and run this code in browser.

## Step 7: Setup babel
Install babel core and babel presets
`npm i -D @babel/core @babel/preset-env @babel/preset-react`
We will use babel to transform our jsx to code compatible with modern browsers.
Create a file .babelrc - this is a configuration file for babel

![babel config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uwtfzwilmsh5hbw7h8pp.png)

Presets in babel are set of some functions that help in transforming code. 
**@babel/preset-env** - It has some set of methods which converts  es6 to standard Javascript.
**@babel/preset-react** - It will transform React(jsx) code to javascript.

## Step 8: Setup Webpack
Even though we have done setup for babel, but still there is no way to merge multiple files and bundle it one file.
To bundle our react code and inject it in html file as script, we will use Webpack.

Create a file **webpack.config.js** in root directory.
First we need to define is entry and output.

```
module.exports = {
    entry: "",
    output: ""
}
```
After updating entry and output

```
const path = require('path');
module.exports = {
    entry: path.join(__dirname, 'src/index.js'),
    output: {
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js'
     }
}
```
You can easily understand above code, where we have used standard node module **path** to give path of '/src/index.js' as entry and '/dist/bundle.js' as output.

Before we proceed, lets install webpack dependencies we need.

`npm i -D webpack webpack-cli babel-loader html-webpack-plugin`

I will explain each dependencies why we are using them.

**webpack** - It is a main webpack library, without this our configuration will not work.
**webpack-cli** -It will allow us to use webpack commands, using this we can run our server and build our code. Otherwise we will not be able to execute our webpack configuration.
**babel-loader** - Loaders in webpack are responsible for transforming code, here babel-loader will use .babelrc configuration and transform our es6 and jsx code to standard and compatible javascript that will be supported by browsers.
**html-webpack-plugin** - In webpack, we can also configure some plugins, this plugin will use our html file as template and this will inject bundle.js as script in html.

Lets use these libraries to configure it further.

## Step 9: Resolve Extensions
**resolve** is a special property in webpack configuration that tells webpack to read these extensions. If we don't define this, we will get error as "Unable to resolve App.jsx' or something like this. 
![resolve extensions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sv8ywxxnpshmacvj14w6.png)

Now that webpack knows it needs to resolve these two types of files.

## Step 10: Configure Loaders

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

module.exports = {
    entry: path.join(__dirname, 'src/index.js'),
    output: {
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    resolve: {
        extensions: ['.js', '.jsx']
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            }
        ]
    }
}
```

Without a loader, we can not transform our code. To configure a loader we define it under **module**. We can add many rules, each rule will have a loader.
In above code, this will work for only js and jsx file and will exclude node_modules. 

## Step 11: Configure plugin
If you remember we installed one plugin, **html-webpack-plugin**. Now its time to use this.

```
   plugins: [
        new HtmlWebpackPlugin({ template: './public/index.html'})
    ]
```

## Step 12: Install and setup Dev server
To setup dev server, lets install a dependency provided by webpack for dev server
`npm i -D webpack-dev-server`

```
 devServer: {
        hot: true,  // hot reloading
        port: 3000,  // port on which server will run
        open: true // open browser automatically on start
    }
```
Add above properties. 

So our final configuration will be,

```
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: path.join(__dirname, 'src/index.js'),
    output: {
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    resolve: {
        extensions: ['.js', '.jsx']
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({ template: './public/index.html'})
    ],
    devServer: {
        hot: true,
        port: 3000,
        open: true
    }

}
```

## Step 13: Configure script to run our server.

Add below scripts in package.json

```
  "scripts": {
    "start": "webpack serve --mode development",
    "build": "webpack --mode production"
  },
```
 
After all these 13 steps, now its time to test our server
Run below command in terminal
`npm start` this will open app in our default browser.
`npm run build` this will create a dist folder with bundle file.

To avoid using in every file

```
import React from 'react';
```

update your .babelrc with below code

```
{
    "presets":[
        "@babel/preset-env",
        ["@babel/preset-react", {"runtime": "automatic"}]
    ]
}
```
If you noticed we have added { "runtime" : "automatic" }
This will make React object globally available.

At the end of this you will have two things,
1. Running server

![running server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sy4io9fgif85j4d452o3.png)
2. build files

![Build files](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n1s4jlnoj9fsst2clcul.png)

Hope it was easier to understand, if something did not work comment it out.

Happy Learning!