Setting Up React, Babel, & Webpack Without Create-React-App🚀
Tags: react, webpack, frontend, babel
Published: 2022-09-03 22:52:00

First things first, why would anyone want to create a react application manually when we have one line installations like: 
```powershell
npx create-react-app <application-name>
```
Well, as there is nothing wrong with setting up a react application utilizing this method. We can can learn a lot by seeing what goes on under the hood by doing everything manually. Furthermore, we get the added benefit of having more control over the different processes of loading your front-end onto a browser.

**<u>Versions Being Used:</u>**
- React 18
- Babel 7
- Webpack 5

<br />
# Pre-Setup
**<u>Background Information:</u>** In order to get started we need to begin by installing a package manager. A package manager is a tool developers utilize in order to manage the various software packages. This ranges from installation, upgrading, removing, and dependency resolution. One of the most popular options we will look at is `NPM`.

###1. Node Version Manager (NVM) Installation
We will first be installing a node version manager in order to easily keep track, and manage different versions of node. Since the focus of this article is not about package managers, please follow this article about how to download [here](https://linuxhint.com/install-nvm-windows/).
<br />

###2. Node Installation
Now that you have `NVM` installed, you can run the following script:
```powershell
nvm install <Node Version>
```
or install the latest version of Node:
```powershell
nvm install node
```
finally, to use the specific node version run:
```powershell
nvm use <Node Version>
```
and that is it! You should be good to get officially started.
<br />
# Setting up the project
###1. Initializing package.json
**<u>Why use package.json:</u>** We use the package.json in order for npm (or yarn) to identify your project and understand how to handle the project's dependencies along with:
- Start your project
- Run scripts
- Install dependencies
- Publish to the NPM registry

**<u>Initializing package.json:</u>** Now that you know a little more about the importance of having the package.json, run either of the following commands to initialize the file:
```powershell
npm init
```
or 
```powershell
npm init -y
```
the difference between the two is that the `-y` will, by default, say yes to every prompted question. The following questions will be presented if you decide to omit the `-y`:
```powershell
package name: (package-name-here)
version: (version)
description: (description of package)
entry point: (file used to start the project)
test command: (script to run test on project)
git repository: (where source code is located)
keywords: (indexed by the NPM registry to find packages when searched)
author: (author of package)
license: (kind of license applied) (typically MIT or ISC)
```
Learn more about package.json [here](https://heynode.com/tutorial/what-packagejson/). 
<br />

###2. Initializing React
Run the following command in the terminal:
```powershell
npm install --save-dev --save-exact react react-dom
```
**<u>Packages Explained:</u>**
- [react](https://www.npmjs.com/package/react)
    - Will only have the needed functionality in order to define your React components.
- [react-dom](https://www.npmjs.com/package/react-dom) 
    - Serves as the entry point to the DOM and server renders for React.

After the command is run, the following will be created:
- node_modules
    - Used to hold all downloaded dependencies from npm.
- package-lock.json
    - Used to keep track of exact version of every package installed along with the dependency tree of every package.

*** NOTE: the `--save-dev` will save these packages as a dev-dependency. `--save-exact` will save the exact package. ***
<br />

###3. Initializing Babel
**<u>Why use babel:</u>** Babel is a JavaScript compiler that converts modern JavaScript into code that can be backwards compatible with older versions of web browsers and environments.
<br />

Now that you understand the need for babel, run the following command:
```powershell
npm install --save-dev --save-exact @babel/core @babel/preset-env @babel/preset-react babel-loader
```
- [@babel/core](https://babeljs.io/docs/en/babel-core)
    - Babel compiler core.
- [@babel/preset-env](https://babeljs.io/docs/en/babel-preset-env)
    - Babel preset for each environment.
- [@babel/preset-react](https://babeljs.io/docs/en/babel-preset-react)
    - Babel preset for all React plugins.
- [babel-loader](https://webpack.js.org/loaders/babel-loader/)
    - Allows transpiling JavaScript files using Babel and Webpack.

Now, create a configuration file called `.babelrc` and paste the following code:
```json
{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ]
  ]
}
```
These presets is to activate the package when processing this configuration file. 

We are also going to be utilizing React's JSX transform from React 17. In order to achieve this we have to set the "runtime" to "automatic". In Babel 8 the default runtime will be set to automatic.
<br />

###4. Initializing Webpack (and other basic needs)
Now it is time to install webpack and any other necessary packages. Run this line in the terminal:
```powershell
npm install --save-dev --save-exact webpack webpack-cli webpack-dev-server
```
- [webpack](https://www.npmjs.com/package/webpack)
    - Module bundler with the main purpose to bundle JavaScript files for the browser.
- [webpack-cli](https://www.npmjs.com/package/webpack-cli)
    - Command Line Interface (to execute webpack terminal lines).
- [webpack-dev-server](https://www.npmjs.com/package/webpack-dev-server)
    - Utilize webpack with a development server to provide live reloading.

Now, run the following script:
```powershell
npm install --save-dev --save-exact html-webpack-plugin style-loader css-loader file-loader
```
- [html-webpack-plugin](https://webpack.js.org/plugins/html-webpack-plugin/)
    - Simplifies creation of HTML files to serve your bundles.
    - This plugin is useful when webpack bundles include a hash in the file name. Learn more about the importance of hash [here](https://survivejs.com/webpack/optimizing/adding-hashes-to-filenames/).
- [file-loader](https://www.npmjs.com/package/file-loader)
    - Resolves import/require() on a file into a url and emits the file into the output directory.
- [css-loader](https://webpack.js.org/loaders/css-loader/)
    - Interprets import and url like import/require and will resolve them.
- [style-loader](https://www.npmjs.com/package/style-loader)
    - Inject CSS into the DOM.

Finally, at the root of the project, create a webpack.config.js file and write the following:
```javascript
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");

module.exports = {
  entry: "./src/index.js",
  mode: "development",
  output: {
    filename: "bundle.[fullhash].js",
    path: path.resolve(__dirname, "dist")
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html"
    })
  ],
  resolve: {
    modules: [__dirname, "src", "node_modules"],
    extensions: ["*", ".js", ".jsx", ".tsx", ".ts"]
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: ["babel-loader"]
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: ["style-loader", "css-loader"]
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        exclude: /node_modules/,
        use: ["file-loader"]
      }
    ]
  }
}
```
- Entry:
    - Indicates which module webpack should use to begin building out its internal dependency graph. From that entry point, webpack will figure out which other modules and libraries that entry point is dependent on. Learn more about Entry [here](https://webpack.js.org/configuration/entry-context/#entry).
- Output:
    - Tells webpack where to emit the bundles it creates and how to name these files. Learn more about Output [here](https://webpack.js.org/concepts/output).
- Plugins:
    - Plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment. Learn more about Plugins [here](https://webpack.js.org/concepts/plugins).
- Resolve:
    - Changes how the modules are resolved. Learn more about Resolve [here](https://webpack.js.org/configuration/resolve/).
- Modules:
    - This field can also be called "Loaders" and allows webpack to process other types of files and convert them into valid modules that can be consumed by your application and added to the dependency graph. This is done because webpack only understands JavaScript and JSON files. Learn more about Loaders [here](https://webpack.js.org/concepts/loaders).
<br />

#Time to Program!
###1. Create Hello, World!
Create a folder called "src" with the following files:
- App.js
```javascript
const App = () => (
  <div>
    <h1>Hello, World!</h1>
  </div>
);

export default App;
```
- index.js
```javascript
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';

const rootElement = document.querySelector('#root');
if (!rootElement) throw new Error('Failed to find the root element');
const root = createRoot(rootElement);
root.render(
  <StrictMode>
    <App />
  </StrictMode>
);
```
- index.html
```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</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
```
<br />

###2. Run program
Now, in the package.json file, add these lines to your scripts section:
```powershell
"start": "webpack serve --open",
"build": "webpack --config webpack.config.js --mode production"
```
**<u>Command line explained:</u>**
- `npm run start`
    - Serve will run the `webpack-dev-server`
    - `--open` will allow webpack to launch browser automatically
- `npm run build`
    - `--config webpack.config.js` provide path to webpack configuration file
    - `--mode production` defines mode to pass to webpack

Now in the terminal just run `npm run start` and you will see your application run!
<br />

##Bonus!
**<u>Script Commands:</u>** When running the command `npm run build` webpack will build the project and create a "dist" folder. This folder will have all of the information that will be sent to the browser for production mode.

**<u>Package Management:</u>** Every package is currently saved as a dev-dependency. This is done because it is not necessary to send these packages to the client-side since we are going to be transpiling our code to vanilla JavaScript with Babel. The install commands all come with `--save-exact` in order to keep control of all package versions.


View everything together in [Github](https://github.com/RinconCamilo/Setting-React-Webpack). 

If you found this helpful or just enjoyed reading the article, consider grabbing me a [cup of coffee](                    buymeacoffee.com/rinconcami9).