Beginners Guide to Minimal React + Webpack 4 + Babel 7 Project Setup
Tags: react, webpack, babel, beginners
Published: 2020-03-13 15:48:15

React has become the [leading frontend library of choice](https://2019.stateofjs.com/front-end-frameworks/)  among developers in recent years. The best way to learn and practice any programming language tool is to build stuff with it --- in order to so we need to setup a coding playground. The fastest way to get started with such a project is to bootstrap it with `create-react-app (CRA)` . The reason why such a thing exists is because modern Javascript tooling has become an incredibly vast space (hilariously explained  [here](https://hackernoon.com/how-it-feels-to-learn-javascript-in-2016-d3a717dd577f) ). Starter kits such as CRA helps us avoid navigating that landscape and focus on coding the fun stuff. However, it is still essential as developers to know what are some of the key pieces of configuring a project. We will learn just that in this step-by-step guide for a minimal React project setup.

#### We will learn the following in this tutorial:
- basic concepts of Webpack and leverage that to setup our project
- what is Babel, what does it do and why do we need it
- how to integrate React into our project
- how to enable hot module reload

Let's get started by learning the basics of the tools we will use today to configure our first project.

&nbsp;

#### React JS
 [React](https://reactjs.org/)  is a javascript library that has brought about a paradigm shift when it comes to building user interfaces. Developed and maintained by Facebook, it views the world through the lens of small, reusable components. Imagine a Lego set, where we put together blocks to create a structure. Similarly, React components don't mean a whole lot on their own, but when assembled in a systematic way through the hands of an experienced developer, it can become a powerful tool to build beautiful and complex user experiences.

##### Key Features
- Simple, reusable components
- Declarative. Code is more readable and easier to debug. 
- One way data binding. Data strictly flows from parent component to children component(s)
- Virtual DOM. Algorithms calculate the "diff" between current and updated DOM (through user interaction, data received from API calls, etc) to only re-render portions of the view that needs to be updated.
- Performance

&nbsp;

#### Webpack
The official site for  [Webpack](https://webpack.js.org/) describes itself to be a static module bundler --- but I believe it is selling itself short. Yes, it is *that* in the simplest sense, but it can do so much more. Webpack is an incredibly configurable tool that packages all the front end code (js, css, templating engines, static assets) and creates bundles that the browser can download to give your application functionality.

##### Key Features
- Module bundler. Packages front end code into bundles for browser to download.
- Code splitting. The bundles can be broken down further based on the page, functionality etc, so that the browser downloads as less code as possible to run the application.
- Tree shaking. If configured to do so, it will not package dead/unreachable code in the bundle.
- Loaders and plugins. Allows us to extend on the out of the box functionality provided by Webpack.
- **Hot Module Replacement** (HMR). During development, Webpack can swap out JS or CSS modules on the fly to update the UI without refreshing the page.
- Environment specific configurations. For instance, we don't want to minify code in development environment but we absolutely want to do so in production.

&nbsp;

#### Babel
Babel is a javascript transpiler --- it compiles modern JS code into older versions so that older browsers can execute them. The latest versions of most browsers can parse through newer JS features, but legacy browsers can't. We don't want our application to fail to run on those browsers, and *that* is where Babel saves the day.

##### Key Features
- Compiles modern JS code into older versions of JS that older browsers can execute.
- Allows plugins presets to extend on top of its out of the box functionality.

&nbsp;

Alright, now that we've learned the core concepts of the tools we're about to use, let's write some code!

__Please note:__ _It's worth mentioning here that the *node* version in your machine must be 10.15.3 or higher. Check by typing `node -v` in your terminal. If you need an update, or don't have node installed at all, you can get the installer [here](https://nodejs.org/en/)_

&nbsp;

#### Step 1:
Open up your terminal and navigate to a directory where you would like to create your repository.

```
cd ~/Desktop/projects
mkdir minimal-react-webpack-babel && cd $_
mkdir -p src
``` 

This will create a directory named "minimal-react-webpack-babel" where our code will live and a "src" subdirectory inside it.

&nbsp;

#### Step 2:
We need to initialize **package.json** at this point

```
npm init -y
``` 

This will create the file in one go, with most fields being empty (like description and author) and other set to default (like version set to 1.0.0). You can come back later to fill them out appropriately.  

The **package.json** should look like this now

```
{
  "name": "minimal-react-webpack-babel",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

```

&nbsp;

#### Step 3:
Let's install **webpack** and **webpack-cli** in our project.

```
npm install webpack webpack-cli --save-dev
``` 

Pre *v4.0.0* of Webpack used to look for a configuration file to run, but since version 4.0.0, Webpack is able to bundle packages out of the box.  

In a later tutorial, I plan to demonstrate a more advanced setup for Webpack (environment specific configs, linters, test runners, etc) that will build on top of what we're learning today. We will leave it in its bare bones state for now.

&nbsp;

#### Step 4:
Time to install **react** and **react-dom**.

```
npm install react react-dom
``` 

React should be installed as a regular dependency and not as `devDependencies` because we need react available at application runtime and packaged into the production bundle of the application.

Alright, that was quick and easy! Let's move on.

&nbsp;

#### Step 5:
We have to install **Babel** here, along with other necessary presets.

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

__Explanation__: React is written using modern ES6 features that older browsers cannot execute. Therefore, we need to somehow convert the modern syntax into ES5. Webpack cannot perform this action --- this is where Babel steps in to bridge the gap. This process is called *transpiling*.  

We installed three dependencies using the command above:
- `babel/core babel-loader` : the interface between babel and webpack. It allows them to work with each other to produce the final bundle.
- `babel/preset-env`: a preset responsible for transpiling ES6 (or above) to ES5.
- `babel/preset-react`: a present responsible for compiling JSX to regular JS. It is possible to forego installing this dependency, but then we will not be able to write our React components using JSX.  

Great, now that we understand that, let's configure *babel* to use the presets we just installed. First, we will need to create a file called `.babelrc` at the root of the project --- this will contain the config rules.

```
touch .babelrc 
```

This is going to be a hidden file. Open up the file using:

```
open -e .babelrc
```

... and add the following lines and hit save:

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

&nbsp;

#### Step 6:
Let's install a *dev-server* now. Technically, it is possible move forward without the dev-server, but that would mean we will have to *build* our project every time we make code changes to it. That is not the world we want to live in --- we want our application to update as soon as we save our code changes. This process is called **Hot Module Replacement**. In addition to installing the dev-server, slight tweak to the webpack config will enable this feature for us.

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

Now, in order to have webpack *build* our code, we will need to add a script inside the `scripts` property of **package.json**. This will compile our code in `production` mode.

We will also add a *start* script that will spin up our dev server and enable seamless development environment.

```
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode production",
    "start": "webpack-dev-server --open --mode development"
  },
```

&nbsp;

#### Step 7:
The last dependencies we need to install in our project are `html-webpack-plugin` and `html-loader`.

```
npm install html-webpack-plugin html-loader --save-dev
```

-  [html-webpack-plugin](https://webpack.js.org/plugins/html-webpack-plugin/)  will generate the HTML from the React components we're about to write.
-  [html-loader](https://webpack.js.org/loaders/html-loader/) exports the HTML as string *and* can minimize it if we ask it to.

&nbsp;

#### Step 8:
We're done with installing dependencies!! What we need to do now is create an HTML file where React will mount our application. Let's call it `index.html` and put it inside the `src` directory we created earlier.

```
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Minimal React + Webpack 4 + Babel 7 project setup</title>
</head>
<body>
<div id="app-container"></div>
</body>
</html>
```

&nbsp;

#### Step 9:
At this point in time, we will add minimal config rules to **webpack**. We will do so by creating a file called `webpack.config.js` and put *all* our rules there. In a future tutorial, we will build on top of what we are learning today and create *separate* config files for development and production environments. This will allow us to segregate environment specific rules, promoting scalability and maintainability.

Let's create that file at project root

```
touch webpack.config.js
```

... and add the following lines to it:

```
const HtmlWebPackPlugin = require("html-webpack-plugin");

module.exports = {
    devServer: {
        contentBase: './dist',
        hot: true
    },
    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"
        })
    ]
};
```

__Explanation__: These lines are telling **webpack** to do the following:
- *devServer* contains config rules for the server instance we will run to host our application using dev-server. `hot: true` enables hot module replacement.
- pipe *all* files with an extension of `.js` or `.jsx` through **babel-loader**, with the exception of files inside `node_modules` directory.
- use the html plugin and loader we installed in the previous step to generate HTML from React components and the front end packaged code bundle *and* inject the bundle in a `<script/>` tag in the HTML.  

&nbsp;

#### Step 10:
We've reached the end of our setup process -- we're now ready to write some React !!

Let's create a *components* directory inside `src`, and write a simple `App.js` component that prints "Hello World".

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

const App = () => {
    return (
        <div>Hello World</div>
    )
};

export default App;
```

We also need to create `index.js` inside `src` directory --- and import the component we just wrote.

```
import React from 'react';
import ReactDOM from "react-dom";
import App from './components/App.js';

const $container = document.getElementById("app-container");
$container ? ReactDOM.render(<App />, $container) : false;
```

The process is complete --- we've a React project using babel and webpack all on our own!! Now, if we run `npm run start`, webpack will spin up the dev server and open up our application in a browser window. Additionally, since we've enabled hot module replacement, if we make code changes to our application (edit existing "hello world" component, add new components, etc), we will immediately see our application update in the browser!

The finished repo is  [here](https://github.com/all-things-javascript/minimal-react-webpack-babel).

&nbsp;

### Conclusion
There is little doubt that `create-react-app` is the quickest and most convenient way to setup a react project (at the moment). However, it is an incredibly valuable skill to know how modern javascript tooling works --- and how we can piece these tools together to setup a front end project from scratch.

I hope this step by step guide has helped you understand some of that. Thank you for reading and stay tuned for more !!