Setting up React Project from Scratch
Tags: react, javascript
Published: 2020-05-30 15:09:04

[create-react-app](https://github.com/facebook/create-react-app) is great tool to get started with react, it gives us everything we need initially for react learning, hacking some things together or even starting a new project.

But some times we do need to know what is going on behind the scene and most importantly what are all the libraries or tools that are being used under the table.

We will try to understand different tools involved to get up and running with react from scratch. We don't have to remember everything, it just gives us a feeling of knowing that makes us more confident.

So, Let's get started

### First: Create project folder

Create a project directory, it can be anywhere we want. I personally like to keep everything in one place, for me it's `~/repos/...`.

```bash
mkdir react-from-scratch && cd $_
```

Next: Initialize project with npm

```bash
npm init -y
```

* `-y` flag to create default `package.json`, If we don't provide this flag with `npm init` then it will open up a CLI questionnaire. We can read more about this [here](https://docs.npmjs.com/creating-a-package-json-file)

Now we have a directory to hold code for our project.

### Next: Install React and React-DOM

* `react`:  This only contains the functionality necessary to define React components. We can find more on this [here](https://www.npmjs.com/package/react)
* `react-dom`: This serves as the entry point to the DOM. We can find more on this [here](https://www.npmjs.com/package/react-dom)

Lets get them installed now:

```bash
npm install react react-dom -S
```

* `-S` (alternate as `--save`) to save it as dependencies. we don't need to provide this flag it's there by default. But it's good to know that it's there.

### Next: Install babel and required plugins

[Babel](https://babeljs.io/docs/en/) lets us try and use new JavaScript features (ES2015+). So Babel is basically JavaScript transpiler which enables us to write new/modern JavaScript that will be transpiled/converted into backwards compatibility version of JavaScript or widely supported ES5 JavaScript.

We usually customize Babel with preset, `preset` is a set of `plugins` used to support particular language. For us we will be using [`react-preset`](https://babeljs.io/docs/en/babel-preset-react)

We will also need to install babel core (`@babel/core`) which has the core functionality of Babel.

Lets get them installed now:

```bash
npm i -D @babel/preset-react @babel/core
```

* `-D` (alternate as `--save-dev`) to save it as dev dependencies.

***NOTE:*** Do have a look at `@babel/preset-env` which allows us to use the latest JavaScript without needing to micromanage which syntax transforms are needed by our target environment(s). But for this demo we are not specifically targeting any environments, we should be good to proceed, and we don't need to install it. We can read more [here](https://babeljs.io/docs/en/babel-preset-env)

### Next: Install Babel Loader

This allows transpiling JavaScript files using Babel and later webpack will be using it to transpile Modern JavaScript into the JavaScript code that browsers can understand.

```bash
npm i -D babel-loader
```

### Next: Configure Babel

In root folder of our directory, create a file called `.babelrc` and add the below content to it. Here we are basically telling Babel to use this configuration while transpiling.

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

### Next: Install Webpack, Webpack cli (the tool used to run webpack on the command line) and Webpack Dev Server

* `webpack`: It is JavaScript Module bundler. We can read more [here](https://webpack.js.org/concepts/)
* `webpack-cli`:  is required to run the project from the terminal.
* `webpack-dev-server`: This will be use to serve our content.

Lets get them installed now:

```bash
npm i -D webpack webpack-cli webpack-dev-server
```

### Next: Install HtmlWebpackPlugin

It simplifies creation of HTML files to serve our webpack bundles. We can either let the plugin generate an HTML file for us or supply our own template.

The plugin will generate an HTML5 file for us that includes all our webpack bundles in the body using script tags. We can read more about this [here](https://webpack.js.org/plugins/html-webpack-plugin/)

```bash
npm i -D html-webpack-plugin
```

Now, we still need to create `webpack.config.js` for webpack configuration. But to understand it more clearly first we will write our component and get our html out.

As of now, Our project's folder structure should look like this:

```bash
.
├── node_modules
├── package.json
├── .babelrc
```

And, `package.json` should look like this:

```bash
{
  "name": "react-from-scratch",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
		"test": "echo \"Error: no test specified\" && exit 1",
  },
  "keywords": [],
  "author": "Ravi Ojha",
  "license": "ISC",
  "dependencies": {
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "@babel/core": "^7.10.1",
    "@babel/preset-react": "^7.10.1",
    "babel-loader": "^8.1.0",
    "html-webpack-plugin": "^4.3.0",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.11.0"
  }
}
```

### Next: Create Directory and Files for Project
In root of project folder create couple of files add the contents as given below:

```bash
mkdir src && cd $_
touch index.js App.js index.html
```

***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>
```
**Note:**
1. We don't have any `<script>` added into html, this html will be used later as a template for HtmlWebpackPlugin in `webpack.config.js`.
2. We have `div#root` in out html, this is where `react-dom` will inject or attach our root level component.

***App.js***

```bash
import React from 'react';

const App = () => {
  return (
    <div>
      Hello!! This is React Session from Scratch
    </div>
  );
};

export default App;
```

**Note:** This is `App` Component that will be Inserted into DOM

***index.js***

```bash
import React from 'react';
/**
  As suggested in comment the above line was missing,
  -- Thanks Ross.
*/
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<APP/>, document.getElementById("root"))
```
**Note:**
1. Notice we are referring `div#root` to attach our Root Component.
2. This will be our entry point for our application, same will be added in `webpack.conf.js` later.

Now, Lets take a pause and look at our project folder structure, it should be similar to this:

```bash
.
├── node_modules
├── src
		├── App.js
		├── index.html
		├── index.js
├── package.json
├── .babelrc
```

**Note:** Now lets create the `webpack.config.js` file.

### Next: Create Webpack Configuration file

In root of our project create a file called `webpack.config.js` and add the below content to it:

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

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

* `entry`: An entry point indicates which module webpack should use to begin building out its internal dependency graph. For us it is `src/index.js`
* `output`: The output property tells webpack where to emit the bundle file it creates and how to name these files.
* `module:rules[...]:use`: We are specifying which loader to use to transpile our code. For us it will be `babel-loader`.
* `plugin`: We will see multiple plugins to do multiple thing, here we have only used the `html-webpack-plugin` to generate our final html to be served.

**Note:** We are using the `index.html` we created earlier as a template, in here `output:filename` will be inserted as `<script>` tag in our final html to be served.

### Next: Add script in package.json

Add the below content in `script` section in `package.json` like below:

```bash
"scripts": {
    "start:dev": "webpack server"
  },

/**
  As pointed in comment, With latest Webpack It has to be
  * "webpack server"
  Rather than just
  * "webpack-dev-server"
  -- Thanks Aakarshak
*/
```

### Next: Run the application

Run the below command from terminal

```bash
npm run start:dev
```

### Finally: This is what we will get!!

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/i9pexkzfhgq0gdj60pvk.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/s2hlox8q7w1sofn9ii64.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/s1j3xnsp28imk9l7cr5b.png)

Happy Coding!! Thanks for reading.