create-react-app is great tool to get started with react, it gives us everything we need initially for react learning, hacking some things together or even starting a new project.
But some times we do need to know what is going on behind the scene and most importantly what are all the libraries or tools that are being used under the table.
We will try to understand different tools involved to get up and running with react from scratch. We don't have to remember everything, it just gives us a feeling of knowing that makes us more confident.
So, Let's get started
First: Create project folder
Create a project directory, it can be anywhere we want. I personally like to keep everything in one place, for me it's ~/repos/...
.
mkdir react-from-scratch && cd $_
Next: Initialize project with npm
npm init -y
-
-y
flag to create defaultpackage.json
, If we don't provide this flag withnpm init
then it will open up a CLI questionnaire. We can read more about this here
Now we have a directory to hold code for our project.
Next: Install React and React-DOM
-
react
: This only contains the functionality necessary to define React components. We can find more on this here -
react-dom
: This serves as the entry point to the DOM. We can find more on this here
Lets get them installed now:
npm install react react-dom -S
-
-S
(alternate as--save
) to save it as dependencies. we don't need to provide this flag it's there by default. But it's good to know that it's there.
Next: Install babel and required plugins
Babel lets us try and use new JavaScript features (ES2015+). So Babel is basically JavaScript transpiler which enables us to write new/modern JavaScript that will be transpiled/converted into backwards compatibility version of JavaScript or widely supported ES5 JavaScript.
We usually customize Babel with preset, preset
is a set of plugins
used to support particular language. For us we will be using react-preset
We will also need to install babel core (@babel/core
) which has the core functionality of Babel.
Lets get them installed now:
npm i -D @babel/preset-react @babel/core
-
-D
(alternate as--save-dev
) to save it as dev dependencies.
NOTE: Do have a look at @babel/preset-env
which allows us to use the latest JavaScript without needing to micromanage which syntax transforms are needed by our target environment(s). But for this demo we are not specifically targeting any environments, we should be good to proceed, and we don't need to install it. We can read more here
Next: Install Babel Loader
This allows transpiling JavaScript files using Babel and later webpack will be using it to transpile Modern JavaScript into the JavaScript code that browsers can understand.
npm i -D babel-loader
Next: Configure Babel
In root folder of our directory, create a file called .babelrc
and add the below content to it. Here we are basically telling Babel to use this configuration while transpiling.
{
"presets":[
"@babel/preset-react"
]
}
Next: Install Webpack, Webpack cli (the tool used to run webpack on the command line) and Webpack Dev Server
-
webpack
: It is JavaScript Module bundler. We can read more here -
webpack-cli
: is required to run the project from the terminal. -
webpack-dev-server
: This will be use to serve our content.
Lets get them installed now:
npm i -D webpack webpack-cli webpack-dev-server
Next: Install HtmlWebpackPlugin
It simplifies creation of HTML files to serve our webpack bundles. We can either let the plugin generate an HTML file for us or supply our own template.
The plugin will generate an HTML5 file for us that includes all our webpack bundles in the body using script tags. We can read more about this here
npm i -D html-webpack-plugin
Now, we still need to create webpack.config.js
for webpack configuration. But to understand it more clearly first we will write our component and get our html out.
As of now, Our project's folder structure should look like this:
.
├── node_modules
├── package.json
├── .babelrc
And, package.json
should look like this:
{
"name": "react-from-scratch",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
},
"keywords": [],
"author": "Ravi Ojha",
"license": "ISC",
"dependencies": {
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
"devDependencies": {
"@babel/core": "^7.10.1",
"@babel/preset-react": "^7.10.1",
"babel-loader": "^8.1.0",
"html-webpack-plugin": "^4.3.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.11.0"
}
}
Next: Create Directory and Files for Project
In root of project folder create couple of files add the contents as given below:
mkdir src && cd $_
touch index.js App.js index.html
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React App From Scratch</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
Note:
- We don't have any
<script>
added into html, this html will be used later as a template for HtmlWebpackPlugin inwebpack.config.js
. - We have
div#root
in out html, this is wherereact-dom
will inject or attach our root level component.
App.js
import React from 'react';
const App = () => {
return (
<div>
Hello!! This is React Session from Scratch
</div>
);
};
export default App;
Note: This is App
Component that will be Inserted into DOM
index.js
import React from 'react';
/**
As suggested in comment the above line was missing,
-- Thanks Ross.
*/
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<APP/>, document.getElementById("root"))
Note:
- Notice we are referring
div#root
to attach our Root Component. - This will be our entry point for our application, same will be added in
webpack.conf.js
later.
Now, Lets take a pause and look at our project folder structure, it should be similar to this:
.
├── node_modules
├── src
├── App.js
├── index.html
├── index.js
├── package.json
├── .babelrc
Note: Now lets create the webpack.config.js
file.
Next: Create Webpack Configuration file
In root of our project create a file called webpack.config.js
and add the below content to it:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, '/dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: 'babel-loader',
},
],
},
plugins: [
new HtmlWebpackPlugin({ template: './src/index.html' }),
],
};
-
entry
: An entry point indicates which module webpack should use to begin building out its internal dependency graph. For us it issrc/index.js
-
output
: The output property tells webpack where to emit the bundle file it creates and how to name these files. -
module:rules[...]:use
: We are specifying which loader to use to transpile our code. For us it will bebabel-loader
. -
plugin
: We will see multiple plugins to do multiple thing, here we have only used thehtml-webpack-plugin
to generate our final html to be served.
Note: We are using the index.html
we created earlier as a template, in here output:filename
will be inserted as <script>
tag in our final html to be served.
Next: Add script in package.json
Add the below content in script
section in package.json
like below:
"scripts": {
"start:dev": "webpack server"
},
/**
As pointed in comment, With latest Webpack It has to be
* "webpack server"
Rather than just
* "webpack-dev-server"
-- Thanks Aakarshak
*/
Next: Run the application
Run the below command from terminal
npm run start:dev
Finally: This is what we will get!!
Happy Coding!! Thanks for reading.
Top comments (9)
Nice Post.
Just wanted to add the below code Will throw an error on Webpack v4.
"scripts": {
"start:dev": "webpack-dev-server"
},
you need to change it to:
"scripts": {
"start:dev": "webpack serve"
},
Corrected it Aakarshak.
Thanks a lot.
Thanks, Will check that.
Hey man, amazing article!
I just noticed this error in the console (see below).
Just add
import React from 'react;
at the top of your
index.js
file.Hey Ross, Thanks for the tip
I have update the post.
Best way to create app and save time is
npx create-react-app example
Yes but setting up a project from scratch allows you to understand what's inside the "box" :)
Best way to create app and save time is
npx create-react-app example
Nice post