How to build a react project without create-react-app.

The memory of my first react app is still fresh in my memory. I can remember how ridiculously easy it was to set up a new project is using the amazing create-react-app.
But as I go deeper into front end Development, I learned that CRA has many limitations. Don’t get me wrong, CRA is an amazing tool which I still use. But its lack of flexibility made me look for other alternatives.

There are different ways to set a react project without CRA, but in this article, I will show you how to set up a react project using Webpack and Babel.

What is Webpack and Babel?

Basically, webpack is a javascript bundler that bundles your static assets into one big file. Babel is a transcompiler that converts ES6 Javascript to an older version (typically, ES5) of javascript for compatibility on all browsers.
Even though I won’t be going deep into the aforementioned tools, I really recommend that you checkout their respective docs before proceeding.

I am a big fan of yarn, so that’s what I will be using throughout this tutorial.

let’s create our project folder and cd into it.

mkdir react-boiler-plate
Cd react-boiler-plate

We’ll be installing packages, so let’s create a package.json file

yarn init -y

Running this will create a package.json file that will contain the info of our app and all its dependencies. Before installing any package, let’s start by laying the structure of our app. This ,of course, will be simple, nothing complicated.

react-boiler-plate
-public
-src
package.json

Here we have two empty folders and a package.json. Does this structure ring a bell? Yeah, we will be mimicking the structure of our beloved CRA.
Now let’s add some packages. We’ll start with the dependencies.

yarn add react react-dom

These packages are the only required dependencies. Let’s install the dev dependencies. I will be breaking this into two parts — the webpack packages and the Babel package.

Yarn add --dev webpack webpack-cli webpack-dev-server html-webpack-plugin

Tip: the — dev flag is similar to — save-dev in npm

Let’s get over each package. The first package is webpack for assets bundling, webpack-cli will let us use webpack cli. Remember yarn start or npm start in create-react-app ? Webpack-dev-server gives us a development server. It comes with many things including hot reloading, that’s for later.

Let’s move on to installing Babel and its kins.

Yarn add --dev @babel/core @babel/preset-react @babel/preset-env babel-loader style-loader css-loader

So we’ve installed Babel preset for both react and the environment (browser), style loaders to handle the importation of our assets and Babel loader for our javascript files.

Next, let’s create these two files in our root directory.

touch webpack.config.js .babelrc

our project structure should look like this

react-boiler-plate
-public
-src
.babelrc
webpack.config.js
package.json

In our webpack.config.js file, let add some code. There’s lots of different ways to write your webpack config and it all depends on your preference. I will stick to my convention in this article.

First, we’re gonna need to require two packages. One is the path Module that comes with node and the other one is html-webpack-plugin, the package we installed.

const path = require(‘path’);
const HTMLplugin = require(‘html-webpack-plugin’);

Now let’s set up our rules. This will be an array of objects. The objects is for each rule we want to set. In this project, there will be only two rules. You can add as many rules as you want depending on your needs and project. This is one of the many reasons as to why I like webpack — flexibility.

const rules = [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: ‘babel-loader’
}
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [“style-loader”, “css-loader”]
}
];

What just happened end there? In the first object, We’re telling webpack to use babel-loader on all javascript files in our project, but we excluded the node_modules file.
This is also the case in the second object. We are telling webpack to use our style loaders on our .css files. Next let’s export our config.

module.exports ={
entry: path.join(__dirname, ‘src’ ‘index.js’),
Output: {
filename: ‘bundle.js’,
Path: path.resolve(__dirname, ‘./build’)
},
module: {rules},
plugins: [
new HTMLwebpackplugin({
template: ‘./public/index.html’
})
};

Here, we specify our entry and output file. The entry file is not created yet, obviously. This file is similar to the index.js file in create-react-app.
The output file is where our bundled app will be created. We specify the name to bundle.js and the parent folder to build.
The module key is where we set our rules. I see many people put their rules here, but i like to just put it in a constant and then call it here. It makes everything cleaner. we have already done above that we can just do

module:{rules: rules} or module:{rules} (ES6)

The plugins key contains an array of all the plugins we want to use. There are many plugins which you can use in your projects. Here is a list of some. Our webpack.config.js file should look like this:

const path = require(‘path’)
const HTMLplugin = require(‘html-webpack-plugin’)
const rules = [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: ‘babel-loader’
}
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [“style-loader”, “css-loader”]
}
]
module.exports ={
entry: path.join(__dirname, ‘src’ ‘index.js’),
Output: {
filename: ‘bundle.js’,
Path: path.resolve(__dirname, ‘./build’)
},
module: {rules},
plugins: [
new HTMLwebpackplugin({
template: ‘./public/index.html’
})
]
};

Before we forget, let’s create the files we specified above. The index.html in the public folder and the index.js file in the src folder. Our project structure should look like this:

react-boiler-plate
- public
index.html
- src
index.js
.babelrc
webpack.config.js
package.json

We are done with webpack now, let’s configure babel. In our .babelrc file, add the presets we installed earlier. The content of this file should be in JSON format.

“presets”[“@babel/preset-env”,”@babel/preset-react”]

We have finished setting up our react project — well, 90% of it. In our index.html file, let’s add a simple html boilerplate. if you are using vscode, type the exclamation mark and press enter. This will auto generate a HTML document for you. Then add an empty div with the ID of root and save.
Our index.html should look like this:

<!DOCTYPE html>
<html lang=”en”>
<head>
<title>React boilerplate</title>
</head>
<body>
<div id=’root’></div>
</body>
</html>

Next, let’s go to our index.js file in the SRC folder. First we need to
Import React and ReactDom. After that, Let’s create a constant that will store the div that we created in our index.html file.
Our file should look like this:

import React from ‘react’;
import ReactDom from ‘react-dom’;
const root = document.getElementById(‘root’);

Voila! our react project is completed — mostly. Now let us setup up our start and build command . Remember how we use to start a dev server and build our app in a create-react project using yarn start and yarn build ?

webpack-dev-server is an amazing tool that let us do just that. we can create our script, customize how our server should run, also offers hot reloading. You can check out the official documentation here

So let’s head to package.json to set up our scripts. Since we won’t be doing any testing and ejecting, we only need two scripts for this projects — startto start the dev server and build to compile our app.
In the package.json file add to the JSON object add the following code:

"scripts": {
“start”: “webpack-dev-server — mode development — open — hot”,
“build”: “webpack — mode production”
}

save and exit.

Voila!

Our react project is now complete.

yarn start

will start the development server. And if everything is okay, We should see a “hello from react in our” browser.
I know that is a long one, perhaps way too long. You can use this as a boilerplate for all your react projects. You can also customize it and add more functionalities and rules.
If you’re relatively new to webpack, i recommend you to learn more about it. It’s a handy tool that you can’t live without it (at least in my case) as a front end developer.
The whole project is available on my github repo. You can check it out here

A Javascript developer and content creator. I am on a mission to make tech and the web accessible to everyone from any background.