Create a React project without Create-React-App
Tags: react, beginners
Published: 2021-03-28 15:09:19

Most of my React projects have so far been spun up with Create React App. I recently completed a Frontend Masters course where the trainer does a good job explaining how to create a React project from scratch. I thought I would write about it, so that I can remember the steps involved so I can remember and others can learn too:

1. Create a folder in your computer. Open with your code editor.
2. Create a `src` folder in your project and create a file called `index.html`.
3. Add a skeleton HTML file (you can use Emmet) - type `html:5` in your VSCode
4. Inside `<body></body>`, create:

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

5. Create a script tag inside `body`: 

```
<script src="./App.js"></script>
```

6. Create a `style.css` file inside `src` folder and add your CSS in the head of your HTML file: 

```
<link rel="stylesheet" href="style.css">
```

## TOOLING

#### NPM

7. Initialise npm: `npm init -y` (make sure node and npm are installed: `node -v` & `npm -v`). It creates a `package.json` file.

#### PRETTIER

8. `npm i -D prettier`
9. Create `format` script in `package.json`: `"format": "prettier \"src/**/*.{js,html}\" --write"`
10. Run prettier when file is saved by default: install `Prettier` in your code editor. Tick `Editor: Format On Save` (in VSCode) and `Prettier: Require Config`.
11. Create `.prettierrc` file in the root folder of the project:

```
{}
```

Now Prettier will run every time file is saved.

#### ESLINT

12. Install stuff:

`npm i -D eslint eslint-config-prettier`
`npm install -D babel-eslint eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react // config eslint for react`
`npm i -D eslint-plugin-react-hooks // config eslint for hooks`
  
13. Create `.eslintrc.json` config file:

```
{
"extends": [
     "eslint:recommended", 
     "plugin:import/errors",
     "plugin:react/recommended",
     "plugin:jsx-a11y/recommended",
     "prettier", 
     "prettier/react" // << you don't need it anymore since it has been merged into "prettier" https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md#version-800-2021-02-21
],
"rules": {
     "react/prop/types": 0, // unless you do prop types
     "no-console": 1, // it will be a warning
     "react-hooks/rules-of-hooks": 2,
     "react-hooks/exhaustive-deps": 1, // has to do with effects
},
"plugins": ["react", "import", "jsx-a11y", "react-hooks"],
"parserOptions": {
     "ecmaVersion": 2018,
     "sourceType": "module", // means we will be using import export
     "ecmaFeatures": {
          "jsx": true
     }     
},
"env": {
     "es6": true,
     "browser": true,
     "node": true
},
"settings": {
     "react": {
          "version": "detect"
     }
}
}
```

14. Then, inside `package.json` file, we create a new script:

`"lint": "eslint \"src/**/*.{js,jsx}\" --quiet"` // quiet reports errors only https://eslint.org/docs/user-guide/command-line-interface

You can now run `npm run lint`.

#### GITIGNORE

15. Inside root directory, create `.gitignore` file. It won't commit the files/directories in the remote repo. Example used in the course:

```
node_modules/
.DS_Store << if you are in a Mac
.cache/
coverage/
.vscode/
.env
```

#### PARCEL

16. Parcel is extremely hands-off, no config needed. It is a bundler, it bundles your dev code ready for production. Install `npm install -D parcel-bundler`. And then, in `package.json`, we create a new script:

```
"dev": "parcel src/index.html"
```

17. Then when you run `npm run dev` it bundles the code (it creates a `.cache` directory that can be ignored. Bable is built into Parcel.

You will also need a `build` commant to deploy your app in, let's say, Netlify: `"build": "parcel build src/index.html"`. Then, in Netlify, set the build command to be `npm run build` and the publish directory to be `dist`.

#### REACT & REACTDOM

18. `npm i react react-dom`

19. Create `App.js` file inside `src` folder and type:

```
import React from 'react';
import { render } from 'react-dom'; // or >> import REACTDOM from 'react-dom'

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

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