# How to Set up a React App from Scratch

## Why not just use Create-React-App?

Modern tools like [create-react-app](https://reactjs.org/docs/create-a-new-react-app.html) are great for beginners to get quickly into developing a React app. It is an environment that comes with all the tools needed to learn developing a single page application. Since most of the configurations are included for the developer,  it is impossible to know what is going on behind the scenes. This tutorial's main goal is to introduce the reader with the tools needed to create a React app and serve it on a development server.&#x20;

## Getting Started

Let's create a project folder for our application.

```
$ mkdir react-app
$ cd react-app
```

Once in the directory let's initialize a project with npm.

```bash
$ npm init -y
```

* The **`-y`** option generates an npm project without asking any questions. Running the **`ls`** command will output the contents of our directory, and we see that there is a **`package.json`** file that npm has created for us. For more information, on that check out the [docs](https://docs.npmjs.com/cli/init).

### Install React and React-DOM

In order to create a React app, we need to install the `react` package which contains only the functionality necessary to define React components. It is typically used together with a React renderer like `react-dom`  for the web. Go ahead and execute the following commands to install these two packages from npm.

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

Let's look at our `package.json` file again. Here is what the contents of the file should be.

{% code title="/package.json" %}

```javascript
{
  "name": "react-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  }
}
```

{% endcode %}

As you can see, we have react and react-dom included in our dependencies.&#x20;

### Installing Webpack

Webpack is a static module bundler for moder Javascript applications. What this means is Webpack allows you to use Javascript modules which it then bundles all into an output file. One of the problems that Webpack solves is that it manages dependencies for us and then includes a single import file to our HTML page. Without it we would have to write individual script tags to include all of our Javascript files in our HTML page. This also saves the browser from making multiple requests for our resources, and just requests the ouput from Webpack. It will connect for you once you see Webpack in action.&#x20;

In order to use Webpack, we will first need to install the following packages.&#x20;

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

This command installs `webpack` and `webpack-cli`, and saves it in our package.json file as dev dependencies. For now, we don't need to create a configuration file for Webpack.

{% hint style="info" %}
Prior to Webpack 4, it was a requirement to have a webpack.config.js file in the main directory of a web app. Since version 4, it is optional to have a configuration file. We will see shortly that creating the configuration file is useful for many reasons.&#x20;
{% endhint %}

Finally, let's add a webpack command inside our `package.json`file inside scripts.

```
"scripts": {
    "build": "webpack --mode production"
    }
```

### Installing Babel and required Plugins

In order to work with modern javascript features, we need Babel to transpile our modern javascript into a syntax that older browsers can [understand](https://babeljs.io/docs/en/). In order to get a glimpse of how Babel transpiles our javascript code you can visit <https://babeljs.io/en/repl>, and write a modern javascript snippet on the left side and see live the way that Babel transpiles our code on the right side of the screen.&#x20;

For our purposes, we need Webpack to talk to Babel, and that is done through a loader called `babel-loader`. We also need Babel presets in particular the following two [presets](https://babeljs.io/docs/en/presets) :

* `babel preset env` -  used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript.
* `babel preset react` - For converting JSX into regular Javascript.&#x20;

Go ahead and install these dependencies:

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

Now we need to configure Babel. Create a `.babelrc` file in the main directory of your project, and add the following lines to the file.

{% code title="/.babelrc" %}

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

{% endcode %}

This tells Babel, which presets we will be using for transforming our code.&#x20;

### Setting up a Git Repository

At this point it is a good idea to include a version control system to our project. I will be using Git to do that. Here is a [cheatsheet](https://github.github.com/training-kit/downloads/github-git-cheat-sheet.pdf) if you need to brush up your knowledge on Git.&#x20;

Before setting up a Git repository let's create a `.gitignore`file. This file is a plain text **file** where each line contains a pattern for **files**/directories to ignore. Generally, this is placed in the root folder of the repository, and that's what I recommend. However, you can put it in any folder in the repository and you can also have multiple `.gitignore` files. After creating the file add the following lines to it.

```bash
node_modules
dist
```

We can now initialize our Git repository. For that, run the following commands in order.&#x20;

```bash
$ git init
$ git add .
$ git commit -m "Initial Commit"
```

## Configure Webpack

We are ready to configure Webpack in order for it to do its magic. Let's create a file named `webpack.config.js` in our main directory and include the following code inside the file.&#x20;

{% code title="/webpack.config.js" %}

```javascript
module.exports = {
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            }
        ]
    }
};
```

{% endcode %}

The above tells Webpack to go through our source files, and for every file with extension `.js` or `.jsx` pipe the code with the use of `babel-loader` to Babel, so it can transform our code. Observe that, we exclude the `node_modules` folder for obvious reasons.&#x20;

## Writing Javascript Source Code

At this point, we are ready to write our first Javascript code. There is many ways to structure our app, but I prefer creating a `src`directory and keeping the source code there. Inside our `src`folder let's create a `components`folder to store our first React component there.&#x20;

```bash
$ mkdir src
$ cd src
$ mkdir components
$ cd components
$ touch SimpleComponent.jsx
```

Create the first component inside `SimpleComponent.jsx` . First we will import React and create a functional component that returns a `div`with a certain text in it. Here is how that code looks like.

{% code title="/src/components/SimpleComponent.jsx" %}

```bash
import React from 'react';

const SimpleComponent = () => {
    return (<div> Hello, this is React </div>);
}

export default SimpleComponent;
```

{% endcode %}

We export the component and should import it in the [entry point](https://webpack.js.org/concepts/entry-points/) of our app. Webpack will assume the entry point is in `src/index.js`by default, and we will not change that convention. So let's go back a directory, to inside the `src`directory and create a new file `index.js`.

```bash
$ cd ..
$ touch index.js
```

Inside our entry point we need to import the React component from `/src/components/SimpleComponent.jsx`Here is how that looks.&#x20;

{% code title="/src/index.js" %}

```bash
import SimpleComponent from './components/SimpleComponent.jsx';
```

{% endcode %}

At this point we are ready to tell Webpack to build our bundle.  This is called the output produced by Webpack. By default Webpack will create a `/dist/main.js`in our main directory. We can [change](https://webpack.js.org/concepts/output/) that inside `webpack.config.js`if we so desire. Go ahead and tell Webpack to create the first bundle with the following command.

```bash
$ npm run build
```

If you have done everything as described so far, you should see the `main.js` bundle created by Webpack. At this point our project structure looks as follows.

![File Structure / React App](https://2655570325-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MA2NeZ0KtgsZQWKMSAc%2F-MA3HOLlsVilWiZdQFjZ%2F-MA3MJuGOnYyBzQYNfj_%2Freact_tutorial_file_structure.png?alt=media\&token=2c843745-5c17-4111-aec7-e7d94c0c9fb8)

## Here Comes the HTML

At this point you might wonder why haven't we created an HTML file yet. I chose to structure the tutorial in this way, to show that Webpack by itself, does not have anything to do with HTML. All it does is, given an entry point Javascript file, it will take the file, recursively find all the dependencies of our `/src/index.js`entry point file, bundle all this code together, and output it in a single file, in our case `/dist/main.js`.  We can then take this file and include it in an HTML file with the help of `<script>`tag. However there is another approach, which I will take in this tutorial.&#x20;

{% hint style="info" %}
You should not manually include the bundled output to your HTML file. We can tell Webpack to do this for us. The reason that this approach is encouraged is due to the fact that sometimes we won't know ahead of time what the file name of Webpack's output will be. This is especially useful for webpack bundles that include a hash in the filename which changes after every compilation. The latter is useful for [caching](https://webpack.js.org/guides/caching/) purposes.
{% endhint %}

Running the following command will install the [HtmlWebpackPlugin](https://webpack.js.org/plugins/html-webpack-plugin/).

```bash
$ npm install html-webpack-plugin --save-dev
```

Now, modify the Webpack configuration file as shown below.

{% code title="/webpack.config.js" %}

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

module.exports = {
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            }
        ]
    },

    plugins: [new HtmlWebpackPlugin()]
};
```

{% endcode %}

And finally, run the command:&#x20;

```bash
$ npm run build
```

Go to the `/dist`folder created by Webpack, and you will now see an `index.html`created by Webpack. This HTML file, has been linked to the bundled `main.js`file for us. Here is the contents of the autogenerated file `/dist/index.html`.

```markup
<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>Webpack App</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
</head>

<body>
    <script src="main.js"></script>
</body>

</html>
```

However as it stands, this is not what we want. The `dist/index.html`file that was created is not meaningful. It does connect to our `dist/main.js`, however if we open the HTML file in the browser we will see that it is blank. We will fix that in the next section.

## React-DOM Render

So far in our `/src/index.js`file we have only been using React components without rendering them to a DOM. Let's create an `index.html`inside the `src`folder. Note that this is different than the autogenerated `index.html`inside the `dist`folder. In fact, later we will tell Webpack to use the `/src/index.html`as a template for generating the `/dist/index.html`. Assuming that we are in the main directory of our project go ahead and execute the following commands.&#x20;

```bash
$ cd src/
$ touch index.html
```

Now copy and paste the following code into your `/src/index.html`file.&#x20;

{% code title="/src/index.html" %}

```bash
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React App From Scratch</title>
</head>

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

</html>
```

{% endcode %}

The above is a simple HTML file with a single `div`with an id of "root". This is where we will tell React to render our components. To do that, open the `index.js` from inside the `/src`folder and copy and paste the following code in there.&#x20;

{% code title="/src/index.js" %}

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

import SimpleComponent from './components/SimpleComponent.jsx';

ReactDOM.render(<SimpleComponent />, document.getElementById('root'));
```

{% endcode %}

## HTML Loader

We are almost done.The final step is to tell Webpack to use the `/src/index.html`as a template for creating the `/dist/index.html`. Before doing that, we need to tell Webpack, how to load `.html`files. We do this by the help of another loader called: `html-loader`. Navigate to the main folder of our app. Then run:

```bash
$ npm install --save-dev html-loader
```

As we did with `babel-loader`we need to alter the webpack.config.js, to use `html-loader` for processing files with extension `.html`.

```javascript
/webpack.config.js

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

module.exports = {
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            },
            {
                test: /\.html$/i,
                loader: 'html-loader',
            },
        ]
    },

    plugins: [new HtmlWebpackPlugin()]
};
```

Finally, we include one more change in the above config file, to have webpack to use `/src/index.html`as a template for building the `/dist/index.html`.&#x20;

{% code title="/webpack.config.js" %}

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

module.exports = {
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            },
            {
                test: /\.html$/i,
                loader: 'html-loader',
            },
        ]
    },

    plugins: [new HtmlWebpackPlugin({
        template: "./src/index.html",
        filename: "./index.html"
    })
    ]
};
```

{% endcode %}

Now go ahead and open the `/dist/index.html` file that Webpack has generated for us. The code looks as shown below.

{% code title="/dist/index.html" %}

```markup
<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>React App From Scratch</title>
</head>

<body>
    <div id="root"></div>
    <script src="main.js"></script>
</body>

</html>
```

{% endcode %}

And opening the above file in the browser with the **file**:// **protocol,** will greet us with the following page.

![](https://2655570325-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MA2NeZ0KtgsZQWKMSAc%2F-MA42LdwTo4pbw6k5vbz%2F-MA44CceRsSESo_I6jAZ%2FScreenshot%20from%202020-06-17%2021-39-09.png?alt=media\&token=a447135b-e1d9-49fb-b423-83b3279451d2)

I hope the tutorial was useful for you. If you have any suggestions feel free to contact me at `levon.tumanyan@yahoo.ca`.

## Sources

* <https://www.toptal.com/react/webpack-react-tutorial-pt-1>
* <https://www.valentinog.com/blog/babel/>
