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 and learn working with Webpack, Babel and other different technologies that React uses.

Let's get started

What we will need

  • Node: we will be working in a Node environment to install different packages, you will need to have Node installed on your machine. Get it here
  • Babel: as a compiler to convert our code into a backwards compatible version of JavaScript supported by older browsers or environments.
  • Webpack: to bundle our code and files into one file.
  • VSCode: as our code editor. Get it here

don't worry if you don't understand these concepts yet we will get back to them later in more details.

Follow these steps

1. Create a node project

create a new folder, open it in VSCode and run npm init -y this will initialize a new node project and add the package.json file.

npm init -y
Enter fullscreen mode Exit fullscreen mode

2. Install Babel dependencies

Babel is a compiler that converts your modern JavaScript to run in older browsers. Mainly in React we use jsx syntax which is not supported by older browser and we will need Babel to convert it | 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 packages we just installed

  • @babel/core: the core/main package that is needed to use Babel in our project. learn more here
  • babel-loader: enables us to use Babel together linked with webpack (more on this later). learn more here
  • @babel/cli: (optional) allow us to use Babel to compile files directly from the command line. You don't necessarily need this to use React but you may need to use Babel in command line. learn more here
  • @babel/preset-env: used to convert ES6 JavaScript syntax into backward versions of JavaScript supported by older browsers. learn more here
  • @babel/preset-react: used to convert React syntax (jsx) into backward versions of JavaScript supported by older browsers. learn more here

3. Install Webpack dependencies
Webpack is a static module bundler for modern JavaScript applications. it takes 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 along our index.html to make our app run | 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
  • webpack: the actual package that enables us to use webpack in our project
  • webpack-cli: allow us to run webpack commands in the command line
  • webpack-dev-server: the webpack server that will act as our server in development if you are familiar with development servers live-server or nodemon it works the same

4. Install HtmlWebpackPlugin
The HtmlWebpackPlugin simplifies creation of HTML files to serve your webpack bundles. as mentioned above when Webpack bundles all our files, it generate a single JavaScript (know as bundle) that will be served along our html file. HtmlWebpackPlugin handles creation these html files. you can learn more 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 contains only the functionality necessary to define React components. It is typically used together with a React renderer like react-dom for the web. an these are the main dependencies that allows as to actually use React

Run the follow command (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 react in our project
  • react-dom: serves as the entry point to the DOM and server renderers for React. 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 create an index.html file and add the following code

<!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 html file for our app and our whole application will live in that div with id root

  • create a src folder and 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 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
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

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

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

Discussion (3)

Collapse
adeodatus profile image
Adeodatus Abdul

Wow!! great work bro

Collapse
stuartambient profile image
stuartambient • Edited on

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

Collapse
yvad60 profile image
Ivad Yves HABIMANA Author

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