Let’s start a React project without using create-react-app (CRA). CRA is a good project starter but for those who wants a complete control over the building process, we will have to use bundler tools like webpack or yarn.

Prerequisites

  • React.js knowledge
  • Installed and configures NodeJS
  • Installed node package manager (npm)

Steps

Using the command-line, let us follow the following steps:

  1. Create directories and files
mkdir webapp
cd webapp

Let us continue with our src folder and placeholder files

mkdir src
cd src
touch index.html
touch App.js
touch App.css

Our index.html should look like this

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>React without using CRA</title>
</head>
<body>
    <div id="root"></div>
</body>
</html>

App.js

  1. Initialize node modules
npm init -y

This step will generate package.json, our React application entry point.

  1. Install React
npm install react react-dom
  1. Install Webpack
npm install webpack webpack-cli webpack-dev-server
  1. Install Babel

Babel is a transpiler that converts ES6+ codes into backwards-compatible JavaScript. It also converts JSX and React codes that works in our browsers.

npm install @babel/core @babel/preset-env @babel/preset-react babel-loader
  1. Install Style and CSS loaders

Webpack requires loaders. It is a preprocessor that bundles static files such as CSS, fonts, images, etc.

npm install style-loader css-loader
  1. Install html-webpack-plugin

html-webpack-plugin converts our React application into a single html index which we can deploy directly to NGINX or Apache.

npm install html-webpack-plugin copy-webpack-plugin
  1. Configure add dev and build scripts

Open package.json and dev and build values inside the script field.

  1. webpack.config.json

Create a file named webpack.config.js and paste the following codes

const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
    entry: "./src/App.js",
    output: {
        publicPath: "/",
        path: path.resolve(__dirname, "dist"),
        filename: "index_bundled.js"
    },
    mode: "development",
    devtool: "source-map",
    devServer: {
        port: 3000,
        static: {
            directory: path.join(__dirname, "src")
        },
        hot: true,
        liveReload: false,
        historyApiFallback: {index: "index.html"}
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                exclude: /(node_modules)/,
                use: [
                    "style-loader",
                    "css-loader"
                ]
            },
            {
                test: /\.js$/,
                exclude: /(node_modules)/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: ["@babel/preset-react", ["@babel/preset-env", {targets: {node: "18"}}]]
                    }
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve('./src/index.html'),
        }),
        new CopyPlugin({
            patterns: [
                {from: 'src/assets', to: 'assets'}
            ]
        })
    ]
}