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
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
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 aboutbabel-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 aboutbabel cli
here@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
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 serverslive-server
ornodemon
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
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
-
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 thereact
package
after installing all these dependencies your project structure and package.json
file should look like this
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>
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 anApp.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
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 thisindex.js
in thesrc
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/>);
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
7. configure Babel
In the root folder create a file named .babelrc
and add the following code
{
"presets": ["@babel/preset-env","@babel/preset-react"]
}
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')
})
]
};
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 andpath
which is a Node build in package that handles file paths in a node project | learn more about path hereentry: 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',
},
],
},
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 ."
}
10. start your application
run npm start
to start the application
you should see this page in your browser
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)
Thanks for the clear instructions!
Wow!! great work bro
Slight change required on my end - in webpack.config.js
entry: './index.js'
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 @stuartambientThank 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.
Hi @nithincp when starting the server by running
npm run start
ornpm start
for short it is not necessary to build first. Thenpm 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 yourindex.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
Wonderful article. Kudos to the Great work
Beautifully written, and completely approachable for someone new to frontend dev. Great job!
Best documentation