Understanding React Setup: A Manual Approach

Understanding React Setup: A Manual Approach

Introduction

Ever wondered how tools like Create React App work under the hood? Setting up a React development environment manually gives you a deeper understanding of the underlying concepts. In this guide, we'll walk through creating a React environment from scratch, covering essential tools like Webpack and Babel. You'll learn how to transpile code, bundle files, and configure a development server, all while gaining valuable insights into how React applications come to life.

What is React

React is a JavaScript library for building user interfaces, primarily for web applications. It enables developers to create reusable UI components that manage their state and render efficiently in response to data changes.

Role Of Development Environment

The development environment will:

  1. Compile JSX

  2. Transpile JavaScript

  3. Generate index.html file, and

  4. Save and Reload the application

Steps

Step #1: Download and Install Node.js

Download and install Node.js which we use to run the development environment.

Step #2: Create and Initialize a Directory

Create a directory, react-app-from-manual-setup and initialize it

mkdir react-app-from-manual-setup
cd react-app-from-manual-setup
npm init -y

This will create a new empty package.json file which will list all the dependencies.

Step #3: Install Necessary Dependencies

First, we install react@16.12.0,and react-dom@16.12.0by running the following:

npm i react@16.12.0 react-dom@16.12.0

react@16.12.0 and react-dom@16.12.0 are two foundational packages for working with React applications.

react@16.12.0 package provides the core functionality of React. It includes:

  • Components: The building blocks for creating user interfaces. You can define reusable components with props and state to manage UI elements.

  • JSX Syntax: A syntax extension for JavaScript that allows you to write HTML-like structures within your code. These structures are then transformed into regular JavaScript function calls.

  • State Management: React allows components to maintain internal state, which controls how the component behaves and renders.

  • Lifecycle Methods: Components have lifecycle methods that you can use to perform actions at different stages of their lifecycle (e.g., mounting, updating, unmounting).

react-dom@16.12.0 package serves as the bridge between React and the DOM (Document Object Model) of your web page. It offers functionalities like:

  • DOM Manipulation: It allows you to update the browser's DOM by rendering React components.

  • Hydration: This is a process of synchronizing the server-rendered HTML with the in-browser React components, leading to a smoother user experience.

  • Legacy Browser Support: While React itself doesn't directly handle browser compatibility, react-dom provides utilities for supporting older browsers (though using a polyfill library might still be necessary).

Install html-webpack-plugin by running:

npm i html-webpack-plugin --save-dev

html-webpack-plugin plugin simplifies the creation of HTML files to serve your Webpack bundles. This is especially useful for Webpack bundles that include a hash in the filename which changes every compilation.

Step #4: Create a src/ Directory with index.html and index.js Files

Create a src/ Directory with index.html and index.js Files:

    mkdir src
    touch index.html index.js

index.js file acts as the entry point for our React application while index.html provides the initial HTML structure and serves as a container for your React application.

Add the following boilerplate to the index.html file:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Create React Development Environment</title>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

Remarks:

  • This file provides the initial HTML structure for your web page.

  • It includes elements like <head> and <body> tags, along with meta information and styling.

  • Crucially, it contains a div element with a specific ID (usually id="app"). This div acts as a placeholder where your React application will be rendered.

  • When your application starts, the index.js code renders your React components and injects them into the DOM within this div element.

Add the following code to the index.js file:

  // index.js
  import React from "react";
  import { render } from "react-dom";

  const Home = () => {
    return <p>This is a test paragraph!</p>;
  };

  render(<Home />, document.getElementById("app"));

Remarks:

  • This file is the starting point where your React application's execution begins.

  • It typically imports the main React component of your application and renders it using the render function from react-dom.

  • This establishes the initial state of your React application.

Step #5: Configure Webpack

Webpack takes the individual building blocks (JavaScript files, HTML, CSS, images etc.) and combines them into a single, well-structured building (bundled file) that can be easily understood by a browser. It achieves this by:

  • Identifying dependencies: It analyzes your code to understand how different files depend on each other (imports and exports).

  • Bundling: It takes all these files and combines them into a single output file (often named bundle.js). This simplifies browser loading and reduces the number of HTTP requests needed.

  • Loaders: Webpack can't understand everything on its own. It uses loaders like Babel to transform specific file types (like JSX) before bundling them.

Install webpack dependencies by:

    # you can install specific versions if needed
    npm install save-dev webpack webpack-cli webpack-dev-server

Create a file named webpack.config.js at the root of your project. This file will contain the Webpack configuration. Add the following:

  import path from "path";
  import HtmlWebpackPlugin from "html-webpack-plugin";
  import { fileURLToPath } from "url";
  import { dirname } from "path";

  const __filename = fileURLToPath(import.meta.url);
  const __dirname = dirname(__filename);

  export default {
    entry: "./src/index.js",
    output: {
      path: path.join(__dirname, "/dist"),
      filename: "bundle.js",
    },
    module: {
      rules: [
        {
          test: /\.(js|jsx)$/,
          exclude: /node_modules/,
          use: {
            loader: "babel-loader",
          },
        },
      ],
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: "./src/index.html",
      }),
    ],
    devServer: {
      static: {
        directory: path.join(__dirname, "dist"),
      },
      compress: true,
      port: 9000,
    },
  };

The code in this configuration file:

  • sets up a Webpack configuration for a React application.

  • It handles JavaScript and JSX files, generates an HTML file, and starts a development server.

  • The path module is used to construct file and directory paths.

  • The HtmlWebpackPlugin creates the HTML file that renders the React app.

  • The devServer section configures the local development server.

Here is an in-depth summary of what the code does:

  • Necessary Imports:

    • import path from "path";: Imports Node.js path module to work with file paths.

    • import HtmlWebpackPlugin from "html-webpack-plugin";: Imports the HtmlWebpackPlugin, a plugin that simplifies the creation of HTML files to serve your webpack

    • import { fileURLToPath } from "url";: Imports fileURLToPath method from the url module, which converts a file URL to a path.

    • import { dirname } from "path";: Imports dirname method from the path module, which gets the directory name of a path.

  • Determining File Paths:

    • __filename: Gets the absolute file path of the current module.

    • __dirname: Gets the directory path of the current module.

  • Webpack Configuration:

    • entry: Specifies the starting point of your application (./src/index.js).

    • output: Defines where the bundled file should be output (path) and its name (filename: "bundle.js").

    • module.rules: Tells Webpack how to handle different file types.

      • Rule for .js and .jsx files:

        • Uses babel-loader to transpile them.
    • plugins: Specifies plugins to be used during the build process

      • HtmlWebpackPlugin: Creates an HTML file that references the bundled JavaScript (template: "./src/index.html").

      • devServer: Configures the development server

        • Serves static files from the dist directory.

        • Compresses responses for faster loading

        • Runs on port 9000.

Step #6: Configure Babel

We can think of Babel as a translator. Webpack might not understand the latest JavaScript features (JSX, classes etc.) you might be using in your React code. Babel acts as a translator, converting your modern JavaScript code into a version that older browsers can understand (usually ES5). This ensures wider compatibility for your application.

Install Babel packages needed to transform JS to JSX via the following command:

  # save to devDependencies
  npm install --save-dev @babel/core@7.7.7 @babel/node@7.7.7 babel-loader@8.0.6 @babel/preset-env @babel/preset-react

Create a file named .babelrc or babel.config.json at the root of your project. This file will contain the Babel configuration. Then add the following:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}

Remarks:

  • This is how Webpack and Babel work together:

    • In the setup, Webpack uses the babel-loader to identify and process your JSX files.

    • The babel-loader then uses Babel's presets (@babel/preset-env and @babel/preset-react) to convert your code to a compatible format.

    • Finally, Webpack bundles the transformed code with your other files into a single bundle.

Step #7: Update package.json Scripts

In your package.json, add a start script to run your application using Webpack Dev Server

  "scripts": {
  "start": "webpack serve --mode development",
  "build": "webpack --mode production"
  }

Our package.json file should look like this:

{
  "name": "react-app-from-manual-setup",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack serve --mode development",
    "build": "webpack --mode production"
  },
  "type": "module",
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "save-dev": "^0.0.1-security",
    "webpack": "^5.91.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^5.0.4"
  },
  "devDependencies": {
    "@babel/core": "^7.7.7",
    "@babel/node": "^7.7.7",
    "@babel/preset-env": "^7.24.3",
    "@babel/preset-react": "^7.24.1",
    "babel-loader": "^8.0.6",
    "html-webpack-plugin": "^5.6.0"
  }
}

Step #8: Run the Application

Start the application by running:

    npm start

Open your web browser and navigate to http://localhost:9000. You should see your React application running.

Conclusions and Next Steps

Manual Setup vs. Toolchains:

While this manual approach offers a valuable learning experience, it can be time-consuming. Setting up Webpack, Babel, and managing configurations can take away from development time. React toolchains like Create React App, Vite, and Next.js come pre-configured with all the necessary tools and functionalities. This eliminates the need for manual configuration, allowing you to focus on writing code and building your React application faster.

Boosting Productivity:

These toolchains offer additional features that further streamline development. Create React App provides a hot reloading server for instant feedback, while Vite boasts lightning-fast development server speeds. Next.js goes even further, offering features like server-side rendering and automatic code-splitting for optimized performance. By leveraging these tools, you can significantly increase your development speed and efficiency.

Resources

  1. babeljs.io/

  2. webpack.js.org/

  3. react.dev/