How to create a React app without using create-react-app | a step by step guide
Tags: react, node, javascript, webdev
Published: 2022-04-18 21:39:01

Can you set a react project without create-react-app (CRA)? Oh yes, you can! Actually, it's not even that complicated, in this guide, we will create a new react project from scratch without using the normal recommended way of using [create-react-app](https://create-react-app.dev/). In the process, We will learn and work with Webpack, Babel, and many other different technologies that React uses under the hood.

**Prerequisites and tech we will be using**

- **Node**: we will be working in a Node environment to install different packages, you will need to have Node installed on your machine. You can get it [here](https://nodejs.org/)

- **VS Code**: I will be using VS Code as our code editor. You can get it [here](https://code.visualstudio.com/) or use any other editor of your preference.

That's all we will need, let's get started... 

**1. Create a Node project**

Create a new folder, open it in VS Code terminal and run the following command 
```bash
npm init -y
```
This will initialize a new Node project and add the `package.json` file.

**2. Install Babel dependencies**

Babel is a compiler that converts your modern JavaScript into backward-compatible versions to be supported by older browsers or environments. For example, if you have written some ES6 JavaScript and you want to use it in an older browser that only supports ES5 JavaScript, you can use Babel to convert The ES6 code to ES5.

In React, we use the `JSX` syntax and which is a special kind of JavaScript that combines JavaScript and HTML. The `JSX` syntax is not supported by some older browsers so it would not work, That's why we need Babel to convert it into versions that would be supported.
You can learn more about Babel [here](https://babeljs.io/docs/en/)

Run the following command to install Babel dependencies (note that we install them as dev dependencies)

```bash
npm install --save-dev @babel/core babel-loader @babel/cli @babel/preset-env @babel/preset-react
```
Understand the packages we just installed

- `@babel/core`: the core/main package that is needed to use Babel in our project.

- `babel-loader`: As we will be later working with Webpack this package will be used to connect Babel and Webpack to use them together (more on this later). You can learn more about `babel-loader` [here](https://www.npmjs.com/package/babel-loader)

- `@babel/cli`: This package allows us to use Babel from the command line.to use React but you may need to use Babel in the command line. You can learn more about `babel cli`[here](https://babeljs.io/docs/en/babel-cli)

- `@babel/preset-env`: this is a preset (collection) of different babel packages that are needed to convert all ES6 JavaScript syntax into older JavaScript versions. Instead of installing them one by one, they are all together in one package.
You can learn more about @babel/preset-env [here](https://blog.jakoblind.no/babel-preset-env/)

- `@babel/preset-react`: This is also preset that contains babel packages needed to convert **React JSX syntax** into the version of JavaScript supported by older browsers.

**3. Install Webpack dependencies**

Webpack is a static module bundler for modern JavaScript applications. It can take different files and bundles them into a single JavaScript file. When building React apps you will end up with many files with different formats and you will need them bundled in a single JavaScript file that will be severed with the `index.html` to make our app run and bundling this JavaScript will be controlled by Webpack| Learn more about Webpack [here](https://webpack.js.org/concepts/)

Run the following command to install Webpack dependencies (note that we install them as dev dependencies)

```bash
npm install --save-dev webpack webpack-cli webpack-dev-server
```
Let's take time to understand the packages we just installed

- `webpack`: The actual package that enables us to use webpack in our project
- `webpack-cli`: allows us to run webpack commands in the command line
- `webpack-dev-server`: The Webpack server that will act as our server during the development environment. If you are familiar with development servers `live-server` or `nodemon` on a higher level it works the same way.

**4. Install HtmlWebpackPlugin**

The HtmlWebpackPlugin is the package that simplifies the creation of HTML files to serve your Webpack bundles. as mentioned above when Webpack bundles all our files, it can generate a single JavaScript (known as a bundle) that will be served along our HTML file. 

One of the cases you may want to use `HtmlWebpackPlugin` is the case where Webpack may bundle your JavaScript files and the name of the bundle changes every time it bundles. In this case, there is no way to predict the name of the bundle and include it in your `index.html` up front. In this case, you may have your own index.html and provide it to `HtmlWebpackPlugin` and when Webpack bundles it creates a new index.html from the one you provided and and the bundle from Webpack for you. 
You can learn more about `HtmlWebpackPlugin` [here](https://webpack.js.org/plugins/html-webpack-plugin/)

run the following command to install HtmlWebpackPlugin

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

**5. Install React dependencies**
React is a JavaScript library for creating user interfaces.
The React package itself contains only the functionality necessary to define React components therefore it is typically used together with a React renderer like `react-dom` to create elements for the web. `react` and `react-dom` are the main dependencies we need to actually use React in our apps

Run the following command to install React dependencies (note that we install them as main dependencies, not dev)

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

- `react` the actual react package that enables to use of react in our project
- `react-dom`: serves as the entry point to the DOM and server renderers for React. It is the package that is used to create elements into the DOM (document object model) so that React apps can work. It is intended to be paired with the `react` package

after installing all these dependencies your project structure and  `package.json` file should look like this

![package.json snap](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f4drjcyig71wc76ytky2.png)

**6. Add React files**
create a `public` folder and in the created folder create an `index.html` file and add the following code in it

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React App</title>
</head>
<body>
    <div id="root"></div>
</body>
</html>
```
this will be the entry HTML file for our app and our whole React application will live in that `div` with id `root`

- create an `src` folder and in it create an `App.js` file and add the following code 

```javascript
import React from "react";

const App = () =>{
    return (
        <h1>
            Hello world! I am using React
        </h1>
    )
}

export default App
```
We just created our first React component. Note that the name is capitalized as it is a React component

- Back in the root folder create an `index.js` which will be the entry of our app. add the following code (You can also create this `index.js` in the `src` folder and if you do so remember to update the path to match yours) 

```javascript
import React from 'react'
import  { createRoot }  from 'react-dom/client';
import App from './src/App.js'

const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App/>);
```

In the above code, we are getting the div with id `root` we created earlier in our HTML and from this we are using `react-dom` package to inject the content of our `App.js` we added in it.

note that the usage of `react-dom` has changed since react v18 you can learn more about upgrading to React 18 [here] (https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#updates-to-client-rendering-apis)

By now your folder structure should look like this


![folder structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3nhffuov8vhpbwwqdgbt.png)

**7. configure Babel**
In the root folder create a file named `.babelrc` and add the following code 

```javascript
{
    "presets": ["@babel/preset-env","@babel/preset-react"]
}
```
This tells Babel to use packages `@babel/preset-env` and `@babel/preset-react` that we installed earlier to compile our code

**8. configure Webpack**

Create a file named `webpack.config.js` and add the following code

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

module.exports = {
  entry: './index.js',
  mode: 'development',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index_bundle.js',
  },
  target: 'web',
  devServer: {
    port: '5000',
    static: {
      directory: path.join(__dirname, 'public')
},
    open: true,
    hot: true,
    liveReload: true,
  },
  resolve: {
    extensions: ['.js', '.jsx', '.json'],
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/, 
        exclude: /node_modules/, 
        use: 'babel-loader', 
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'public', 'index.html')
    })
  ]
};
```
Let's break down this code

we just created configurations that will be used by Webpack when bundling our react project

- the first two lines are quite straight-forward we are just importing `HtmlWebpackPlugin` that we installed earlier and `path` which is a Node build in package that handles file paths in a node project | learn more about path [here](https://nodejs.org/api/path.html)

- **entry**: specifies the main file (the entry) of our application which will be the index.js file we created

- **output**: specifies where Webpack will put it's files after bundling and we specify the path and the file name of that Webpack bundle

- **target**: specifies where our app will run 

- **devServer**: specifies our development server settings 
    - port: specifies the port our app will run on once started
    - static: specifies the directory webpack will use to serve static files
    - open: automatically open the browser after it had bundled our files
    - hot: enables webpack Hot module replacement exchanges, adds, or removes modules while an application is running, without a full reload. to improve performance 
    - liveReload: automatically update the app as you make changes

- **resolve**: tells Webpack files to consider when building our app you can specifies files with several extensions
- **modules**: where we specify rules about how Webpack will handle different files when building our app

```javascript
module: {
    rules: [
      {
        test: /\.(js|jsx)$/, 
        exclude: /node_modules/, 
        use: 'babel-loader', 
      },
    ],
  },
```
this means tells Webpack that while building when it reaches file with `.js` or `.jsx` extensionto use babel-loader on them (remember babel-loader the package we installed earlier)

- **plugin**: where we specify plugins to use with webpack and we will need `HTMLWebpackPlugin` which will generate html files for our bundles and are twlling it to use our index.html file in the public folder as a template

That's all configurations you need 

**9. add scripts in package.json**
in the package.json file in the scripts object scripts that will be used to run Webpack and start our application 
add scripts as mentioned below

```
"scripts": {
    "start": "webpack-dev-server .",
    "build": "webpack ."
  }
```

**10. start your application**
run `npm start` to start the application

you should see this page in your browser

![final results](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wzys2189d2q6d4bbvuia.png)

Congratulations you have successfully set up react project without create-react app Yay!!!
For reference you can find the code for this article on this [GitHub repository](https://github.com/Yvad60/blog-code-references/tree/create-react-app-from-scratch)