React from scratch Part 1
Tags: react, javascript, beginners, tutorial
Published: 2020-08-29 10:35:41

In this series we will get to know React, Webpack, Babel and Redux. For the first part of this series we will begin with a basic setup. Let's get started!

## Prerequisites
In this guide we will be using npm to install all the dependencies and kick start the project.
So make sure you got npm installed on your machine!

## Basic setup
First of all we create a folder to store our project in and go into it to initialize npm:
```Shell
$ mkdir getting-started-react
$ cd ./getting-started-react
$ npm init -y
```
Now we are gonna add some of our dependencies and a new folder called **src**:

```Shell
$ mkdir src
$ npm i react react-dom
```
Inside that src directory we need to create a file called **index.js** with the following content:
```JSX
import React, { StrictMode } from 'react';
import ReactDOM from 'react-dom';

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

ReactDOM.render(
  <StrictMode>
    <App />
  </StrictMode>,
  document.querySelector('#root'),
);
```
The function **App** returns a div with the content *Hello World*.
After that we call the render method of **ReactDOM** to insert our div into the HTML document.
The div will be inserted into the HTML-Element with the id of **root**.

For the code above to work we need to create such an HTML document.
So let's create a file called **index.html** with this content:
```HTML
<!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>Getting Started: React</title>
</head>
<body>
    <noscript>You need to enable JavaScript to run this app!</noscript>
    <div id="root"></div>
</body>
</html>
```
In this file you see the HTML-Element with the id **root**!

## Webpack and Babel
The next step is to setup our development server and bundle our files, so we can actually see what we just created.
For that we need to add some more dependencies to our project and a new folder:
```Bash
$ mkdir webpack
$ npm i webpack webpack-cli
$ npm i -D @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/plugin-transform-runtime babel-plugin-transform-class-properties html-webpack-plugin webpack-dev-server
```
What exactly did we install here? Here is a small overview, for more information click the links:
- ***[webpack](https://webpack.js.org/):*** Webpacks purpose is to bundle JavaScript files for the usage in the browser. It is highly configurable.
- ***[webpack-cli](https://www.npmjs.com/package/webpack-cli):*** A command line interface for the bundler Webpack.
- ***[html-webpack-plugin](https://www.npmjs.com/package/html-webpack-plugin):*** A plugin for webpack to simplify the generation of HTML files.
- ***[webpack-dev-server](https://www.npmjs.com/package/webpack-dev-server):*** A webpack dev server with live reloading mechanism.
- ***[@babel/core](https://babeljs.io/docs/en/next/):*** Babel takes your ECMAScript 2015 and onwards  and makes it backwards compatible for older browsers.
- ***[babel-loader](https://www.npmjs.com/package/babel-loader):*** To use babel in conjunction with webpack you need this loader for webpack.
- ***[@babel/preset-env](https://www.npmjs.com/package/@babel/preset-env):*** Handles backwards compatibility for older browsers.
- ***[@babel/preset-react](https://www.npmjs.com/package/@babel/preset-react):*** Handles React plugin in babel.
- ***[@babel/plugin-transform-runtime](https://www.npmjs.com/package/@babel/plugin-transform-runtime):*** Reduces code size.
- ***[babel-plugin-transform-class-properties](https://www.npmjs.com/package/babel-plugin-transform-class-properties):*** Transforms static class properties in babel.

Now that we have all our dependencies installed it is time to configure **webpack**, **babel** and our **webpack-dev-server**.
First of all we start with configuring babel by creating a new file in our root directory called **.babelrc** with the following configuration:
```JSON
{
  "presets": 
  [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins": [
    "babel-plugin-transform-class-properties",
    ["@babel/plugin-transform-runtime", {
      "regenerator": true
    }]
  ]
}
```
With that we configured which presets and plugins babel should use.

After that we create our webpack configuration. For that we need a new file called **webpack.config.js** in our webpack directory.
The configuration is as follows:
```JavaScript
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');

const baseURL = path.resolve(__dirname, '..');

module.exports = {
  entry: path.resolve(baseURL, 'src', 'index.js'),
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader",
      }
    ]
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: `${baseURL}/src/index.html`,
      filename: './index.html',
      inject: 'body',
    })
  ]
};
```
We added the *babel-loader* to our webpack config and configured our HtmlWebPackPlugin to find the index.html we created earlier.
For that we used *path* to get the correct path at any time.


Now it is time to get the webpack-dev-server started. To do that we modify our *scripts* in our **package.json**:
```JavaScript
  "scripts": {
    "start": "webpack-dev-server --mode development --open --config ./webpack/webpack.config.js",
    "build": "webpack --mode production --config ./webpack/webpack.config.js"
  },
```
If you run the following command now, a browser window should open and display **Hello World!**
```Bash
$ npm start
```
## More Loaders
Next we will be adding more loaders to our webpack configuration. We need loaders for our stylesheets and for our assets, e.g. PNG-, JPG-Files.
First we go ahead and add the necessary loaders as dependencies to our package.json.
```Bash
$ npm i -D sass sass-loader style-loader css-loader file-loader
```
For this project I chose to use SASS instead of CSS, that's why we need to install the npm package sass too.
Next we install all the loaders necessary to break down our SASS to CSS and then load it into our HTML.
To use these loaders we need to modify our webpack.config.js like that:
```JavaScript
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');

const baseURL = path.resolve(__dirname, '..');

module.exports = {
  entry: path.resolve(baseURL, 'src', 'index.js'),
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader",
      },
      {
        test: /\.s[ac]ss$/i,
        exclude: /node_modules/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            },
          },
          'sass-loader',
        ],
      },
      {
        test: /\.(png|jpe?g|gif)$/,
        loader: 'file-loader'
      }
    ]
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: `${baseURL}/src/index.html`,
      filename: './index.html',
      inject: 'body',
    })
  ]
};
```
Important to note is that the style-loader needs to be the first in the use-array, as webpack loads him as last.
So first we collect all sass and css files and then we load them via the style-loader into the [DOM](https://www.w3.org/TR/WD-DOM/introduction.html).
The file-loader resolves files into a url that you can use in your js-files.

## Styles and assets
Last but not least we will add a scss-file and an image to our project, to see if our loaders work as expected.
For that we create a file called **index.scss** in the src-folder and add the following content:
```SCSS
body {
  background-color: red;
}
```
To use this file we simply add the following line to the import-statements of **index.js**:
```JSX
import './index.scss';
```
If you start your development server now, our project should have a red background color.

Next up we will add a new subfolder to the src-folder called **assets**.
Just put in some random image inside the assets folder.
To display this image we have to change up our index.js like this:
```JSX
import React, { StrictMode } from 'react';
import ReactDOM from 'react-dom';
import './index.scss';
import img from './assets/your-image-name.png';

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

ReactDOM.render(
  <StrictMode>
    <App/>
  </StrictMode>,
  document.querySelector('#root'),
);
```
We import the image at the top of the file and then use it as the src-attribute in the HTML-img-tag.
If you restart your webpack-dev-server via *npm start*, you should be able to see the image you put into the assets-folder.

## Conclusion
So we are done for part 1 of this series. We setup a basic react-app with webpack as our bundler and babel for the backwards-compatibility.
We configured webpack to accept SCSS, HTML, JavaScript and image files.
And we added *webpack-dev-server* as our development server, to quickly see what we changed in the browser.

In the next part we start with creating a real application with react.

All the code for this multipart series can be found in this [GitHub-Repository](https://github.com/JakobKIT/getting-started-react).