React Toolchain, NPM, Webpack, and Babel
In this tutorial, we will be setting up the React toolchain from scratch, exploring the configurations that are handled by Create-react-app. By doing this manually, we will have a better understanding of what happens under the hood.
NPM
Introduction to NPM NPM, short for Node Package Manager, is responsible for managing all the third-party libraries we use in our project. It is installed by default with NodeJS.
Initializing NPM and Webpack Navigate to your empty project directory using the terminal and run npm init -y
to create a new package.json
file with default settings.
To add Webpack to your project, run npm install --save-dev webpack webpack-cli
. This will update the package.json
file and include a new section called devDependencies
.
Creating the Index File Under the src
directory, create a new file called index.js
.
All we need to do now is run Webpack: npx webpack
A new folder (dist) is generated with one file main.js
Babel
Babel is a JavaScript compiler that enables you to write modern JavaScript code that can still run on older browsers. To use Babel, you need to install some dev dependencies by running npm install -save-dev @babel/core @babel/cli @babel/preset-env
. The @babel/core
and @babel/cli
are necessary for compiling files, while @babel/preset-env
is a smart preset that handles syntax transformation without requiring specific environment management. To view code transformation, run npx babel ./src/index.js --presets=@babel/preset-env
.
Adding Babel to Webpack
At the begining, we need to add new dev dependency npm install -D babel-loader
and update webpack.config.js file to include the following changes
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
presets: ["@babel/preset-env"],
},
},
]
}
Now when we run Webpack, it will bundle our transformed code.
Adding React preset
Now, let's transform our project to ReactJS by installing the following dependencies npm install -save react react-dom
and add two new files:
App.js
import React from "react";
class App extends React.Component {
render() {
return <div>This is App Component</div>;
}
}
export default App;
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(<App />, document.getElementById("root"));
Once we run Webpack we will get a syntax error saying that it is unable to tranform
To solve this issue, we need to add a new preset for React npm i -D @babel/preset-react
and update webpack.config.js file
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
presets: ["@babel/preset-env", "@babel/preset-react"],
},
},
]
}
Adding HTML Loader
To auto-generate HTML file with the latest bundle we need to add new Depenecey npm i -D html-webpack-plugin
and modify webpack.config.js file by adding new plugin as follow:
const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
],
Adding webpack-dev-server
Webpack-dev-server will provide live reloading to our application. First install webpack-dev-server by npm i -D webpack-dev-server
. And run npx webpack-dev-server
.
to customize Running port add devServer to Webpack configuration
devServer: {
port: 3000,
},
Adding CSS loader
To load CSS files into JavaScript using Webpack and Babel we need a special presets for that npm i -D css-loader style-loader
Update Webpack configuration file by adding new rule under the modules section
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
exclude: /node_modules/,
},
Adding Babel Plugins
Now, change App.js file to the following:
import React from 'react'
class App extends React.Component {
state = {
count: 0
}
render() {
return (
<div>
<h1>Hello World!</h1>
<h2>Count: {this.state.count}</h2>
<button onClick={() => this.setState(state => ({count: state.count + 1}))}>+</button>
<button onClick={() => this.setState(state => ({count: state.count - 1}))}>-</button>
</div>
)
}
}
export default App
Bable will now give us a new syntax error because defining a state outside constructor is not supported by javascript doesn't support such syntax. We need to add a new plugin to Babel ( Before we added html-webpack-plugin as Webpack plugin). Install npm i -D @babel/plugin-proposal-class-properties
, and now we need to update Webpack configuration as following:
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
devServer: {
port: 3000,
},
devtool: "source-map",
output: {
path: path.join(__dirname, "build"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
presets: ["@babel/preset-env", "@babel/preset-react"],
plugins: ["@babel/plugin-proposal-class-properties"],
},
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
],
};