DEV Community

Cover image for How to create a React app without using create-react-app | a step by step guide
Ivad Yves HABIMANA
Ivad Yves HABIMANA

Posted on • Updated on

How to create a React app without using create-react-app | a step by step guide

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. 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

  • VS Code: I will be using VS Code as our code editor. You can get it here 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

npm init -y
Enter fullscreen mode Exit fullscreen mode

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

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

npm install --save-dev @babel/core babel-loader @babel/cli @babel/preset-env @babel/preset-react
Enter fullscreen mode Exit fullscreen mode

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

  • @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 clihere

  • @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

  • @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

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

npm install --save-dev webpack webpack-cli webpack-dev-server
Enter fullscreen mode Exit fullscreen mode

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

run the following command to install HtmlWebpackPlugin

npm install --save-dev html-webpack-plugin
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode
  • 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

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

<!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>
Enter fullscreen mode Exit fullscreen mode

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
import React from "react";

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

export default App
Enter fullscreen mode Exit fullscreen mode

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)
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/>);
Enter fullscreen mode Exit fullscreen mode

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

By now your folder structure should look like this

folder structure

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

{
    "presets": ["@babel/preset-env","@babel/preset-react"]
}
Enter fullscreen mode Exit fullscreen mode

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

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')
    })
  ]
};
Enter fullscreen mode Exit fullscreen mode

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

  • 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

module: {
    rules: [
      {
        test: /\.(js|jsx)$/, 
        exclude: /node_modules/, 
        use: 'babel-loader', 
      },
    ],
  },
Enter fullscreen mode Exit fullscreen mode

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 ."
  }
Enter fullscreen mode Exit fullscreen mode

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

you should see this page in your browser

final results

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

Top comments (9)

Collapse
 
adeodatus profile image
Adeodatus Abdul

Wow!! great work bro

Collapse
 
agamemnun profile image
Bülent T. Yüksel

Thanks for the clear instructions!

Collapse
 
stuartambient profile image
stuartambient • Edited

Slight change required on my end - in webpack.config.js entry: './index.js'

Collapse
 
ivadyhabimana profile image
Ivad Yves HABIMANA

Actually your version is more correct as we have to specify the path tou our entry file which should be ./index.js. Thanks for mentioning @stuartambient

Collapse
 
nithincp profile image
Nithin Chandran P

Thank you for the wonderful and in-depth explanation.
I apologize for posting this comment a bit late. However, I would like to mention an issue I encountered. I believe that before starting the server, it is necessary to perform the build process, correct? I faced an issue stating 'module not found' initially. However, once I performed the build and then started the server, everything worked fine. Please confirm if I interpreted it correctly.

Collapse
 
ivadyhabimana profile image
Ivad Yves HABIMANA

Hi @nithincp when starting the server by running npm run start or npm start for short it is not necessary to build first. The npm run build command just creates an optimized version of your React code and bundles all your React files (code) into one JavaScript file that is sent to your index.html file, This should have no effect on your development environment.
I don't think it worked because you ran the build command because it should work even without it

Collapse
 
codewithprabhat profile image
codewithprabhat

Wonderful article. Kudos to the Great work

Collapse
 
aman4you profile image
aman4you

Best documentation

Collapse
 
timmyjose profile image
Timmy Jose

Beautifully written, and completely approachable for someone new to frontend dev. Great job!