Start a React Project Truly from Scratch Using Webpack and Babel

Facebook did an excellent job building Create React App — a powerful CLI tool that allows React developers to generate new React projects with absolute ease. Create React App comes with a wide array of features out-of-the-box, including a pre-configured build setup.

Under the hood, it uses Babel and Webpack, but you don’t need to know anything about them.

- Official React Documentation

Create React App’s ability to concoct a single-page React application in seconds to minutes without the need for manual installation and configuration of Webpack and Babel is precisely what makes it a staple in so many React projects. However, it is important for developers to have a good understanding of what their tools are doing under the hood. The best way to learn how Webpack and Babel work to make a React project tick is by building a React project from scratch using these tools. But first, here is a gentle introduction to Webpack and Babel.

Webpack is a module bundler; as the name implies, it bundles every module that a project needs into one or more bundles that can be referenced in the primary html file.

For example, when building a JavaScript application that has JavaScript code separated into multiple files, each file must be loaded into the primary html file using the <script> tag.

<body>
...
<script src="libs/react.min.js"></script>
<script src='src/header.js'></script>
<script src='src/dashboard.js'></script>
<script src='src/api.js'></script>
<script src='src/something.js'></script>
</body>

By implementing the use of Webpack, these separate JavaScript files can be intelligently bundled into one file that can then be loaded into the primary html file.

<body>
...
<script src='dist/bundle.js'></script>
</body>

In this instance, using Webpack not only dramatically reduces the number of imports but also eliminates any issues that may arise if the scripts are not loaded in order. Besides module bundling, Webpack also offers Loaders and Plugins which can be used to transform files before, during, or after the bundling process. Loaders and Plugins are explored in further detail later on in this article.

Babel is a JavaScript compiler that transforms ECMAScript 2015+ code into a version of JavaScript that is compatible across all web browsers and environments.

When building a website or a web application, it is important to ensure that it works well on all major browsers. However, the latest and greatest features of today’s JavaScript code may not yet be fully supported by all browsers. By using Babel, any code that contains newer JavaScript syntax can be converted into old JavaScript code that is understood by all browsers and environments (such as Node).

Modern JSX syntax in React applications can be transformed to older compatible code by using Babel’s React preset, which is explored in further detail later on in this article.

  • First, create a new directory for the project. Then navigate into the directory and initialize a brand new npm project which creates a new package.json file within the directory.
mkdir react-webpack-babel
cd
react-webpack-babel
npm init -y
  • Next, install the react and the react-dom packages.
npm install react react-dom
  • Create a .gitignore file in the root of the project directory to maintain a list of files and folders that don’t need to be pushed to GitHub. Make sure to include the following in the list.
node_modules
.DS_Store
dist
  • Next, create a new folder in the root of the project directory and name it app. Inside the new app folder, create index.html, index.css, and index.js files.
Current file structure.
  • Include the following code in the index.html file. The div with the id of app is where the Hello World component will eventually be rendered to.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial- scale=1.0">
<title>React Webpack Babel</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
  • Now, include the following code in the index.js file. The following code closely resembles the code that is included in the index.js file created by the Create React App tool.
import React from 'React';
import ReactDOM from 'react-dom';
import './index.css';function HelloWorld() {
return (
<h1>Hello World!</h1>
)
}
ReactDOM.render(<HelloWorld />, document.getElementById('app'));
  • The code as it is now, won’t run because Webpack and Babel haven’t been configured yet. Install the following packages in order to kickstart the configuration process.
npm install --save-dev webpack webpack-cli webpack-dev-server babel-loader css-loader style-loader html-webpack-plugin
  • The webpack package, as the name implies, is the package required to run Webpack in a project. The webpack-cli is required when using Webpack v4 or later. The webpack-dev-server is a development server that offers live reloading.
  • Next, create a webpack.config.js file in the root of the project directory. This file will include all the configuration options that are needed to bundle the app together, including loaders and plugins (like the ones just installed) that can make certain transformations to the bundle.
  • Include the following code in the webpack.config.js file.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './app/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js'
},
module: {
rules: [
{ test: /\.(js)$/, use: 'babel-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }
]
},
mode: 'development',
plugins: [
new HtmlWebpackPlugin({
template: 'app/index.html'
})
]
}
  • Webpack requires path because it deals with the file-system when bundling the app. The module.exports defines an object that Webpack will export using the configuration options specified within the object.
entry: './app/index.js'
  • The very first option defined is the entry point of the application, which is basically the primary module of the application from which Webpack begins the bundling process. As more modules are created and imported into the primary module, Webpack will bundle all of them into one single file.
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js'
}
  • The output option tells Webpack where to put the bundled app. In this instance, Webpack will create a dist folder in the root of the project directory and subsequently place the bundled file which will be called index_bundle.js
module: {
rules: [
{ test: /\.(js)$/, use: 'babel-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }
]
}
  • The rules array within module specify which file types need transforming and which loader to use in order to make those transformations. The file types need to be specified as a value to the test key using regular expressions. In this instance, Webpack will use the babel-loader transformation on all JavaScript files it comes across during the bundling process. Similarly, it will use the style-loader and the css-loader transformations on all CSS files.
mode: 'development'
plugins: [
new HtmlWebpackPlugin({
template: 'app/index.html'
})
]
  • Unlike loaders, which transform files before or during the bundling process, plugins make transformations after the bundle has been generated. Similar to rules, plugins is an array that has a new instance of the HtmlWebpackPlugin — a plugin that generates a new html file modeled after the existing index.html file and references the bundled JavaScript code.
  • Next, install the following Babel presets. These presets define the transformations that need to be made to the modern JavaScript code and JSX used in the project.
npm install --save-dev @babel/core @babel/preset-env @babel/preset-react
  • In the package.json file, create a new property called babel that includes a preset array containing the two installed presets.
"babel": {  "presets": [     "@babel/preset-env",     "@babel/preset-react"
]
}
  • Next, create a script that runs the webpack-dev-server.
"scripts": {
"build": "webpack serve"
}
  • Finally, to run the app in Webpack’s development server, enter the following command into the terminal.
npm run build
  • The app should now run on localhost:8080/

That concludes this article on starting a React project truly from scratch using Webpack and Babel. As the project grows, there may be a need for loaders and plugins that are not discussed in this article. Refer to this comprehensive list of loaders and plugins to learn and identify ones that can facilitate a larger React app.

Front-End Developer and Designer