Setting Up React, Babel, & Webpack Without Create-React-App🚀

rinconcamilo

Camilo Rincon

Posted on September 3, 2022

Setting Up React, Babel, & Webpack Without Create-React-App🚀

First things first, why would anyone want to create a react application manually when we have one line installations like:

npx create-react-app <application-name>
Enter fullscreen mode Exit fullscreen mode

Well, as there is nothing wrong with setting up a react application utilizing this method. We can can learn a lot by seeing what goes on under the hood by doing everything manually. Furthermore, we get the added benefit of having more control over the different processes of loading your front-end onto a browser.

Versions Being Used:

  • React 18
  • Babel 7
  • Webpack 5

Pre-Setup

Background Information: In order to get started we need to begin by installing a package manager. A package manager is a tool developers utilize in order to manage the various software packages. This ranges from installation, upgrading, removing, and dependency resolution. One of the most popular options we will look at is NPM.

1. Node Version Manager (NVM) Installation

We will first be installing a node version manager in order to easily keep track, and manage different versions of node. Since the focus of this article is not about package managers, please follow this article about how to download here.

2. Node Installation

Now that you have NVM installed, you can run the following script:

nvm install <Node Version>
Enter fullscreen mode Exit fullscreen mode

or install the latest version of Node:

nvm install node
Enter fullscreen mode Exit fullscreen mode

finally, to use the specific node version run:

nvm use <Node Version>
Enter fullscreen mode Exit fullscreen mode

and that is it! You should be good to get officially started.

Setting up the project

1. Initializing package.json

Why use package.json: We use the package.json in order for npm (or yarn) to identify your project and understand how to handle the project's dependencies along with:

  • Start your project
  • Run scripts
  • Install dependencies
  • Publish to the NPM registry

Initializing package.json: Now that you know a little more about the importance of having the package.json, run either of the following commands to initialize the file:

npm init
Enter fullscreen mode Exit fullscreen mode

or

npm init -y
Enter fullscreen mode Exit fullscreen mode

the difference between the two is that the -y will, by default, say yes to every prompted question. The following questions will be presented if you decide to omit the -y:

package name: (package-name-here)
version: (version)
description: (description of package)
entry point: (file used to start the project)
test command: (script to run test on project)
git repository: (where source code is located)
keywords: (indexed by the NPM registry to find packages when searched)
author: (author of package)
license: (kind of license applied) (typically MIT or ISC)
Enter fullscreen mode Exit fullscreen mode

Learn more about package.json here.

2. Initializing React

Run the following command in the terminal:

npm install --save-dev --save-exact react react-dom
Enter fullscreen mode Exit fullscreen mode

Packages Explained:

  • react
    • Will only have the needed functionality in order to define your React components.
  • react-dom
    • Serves as the entry point to the DOM and server renders for React.

After the command is run, the following will be created:

  • node_modules
    • Used to hold all downloaded dependencies from npm.
  • package-lock.json
    • Used to keep track of exact version of every package installed along with the dependency tree of every package.

*** NOTE: the --save-dev will save these packages as a dev-dependency. --save-exact will save the exact package. ***

3. Initializing Babel

Why use babel: Babel is a JavaScript compiler that converts modern JavaScript into code that can be backwards compatible with older versions of web browsers and environments.

Now that you understand the need for babel, run the following command:

npm install --save-dev --save-exact @babel/core @babel/preset-env @babel/preset-react babel-loader
Enter fullscreen mode Exit fullscreen mode

Now, create a configuration file called .babelrc and paste the following code:

{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ]
  ]
}
Enter fullscreen mode Exit fullscreen mode

These presets is to activate the package when processing this configuration file.

We are also going to be utilizing React's JSX transform from React 17. In order to achieve this we have to set the "runtime" to "automatic". In Babel 8 the default runtime will be set to automatic.

4. Initializing Webpack (and other basic needs)

Now it is time to install webpack and any other necessary packages. Run this line in the terminal:

npm install --save-dev --save-exact webpack webpack-cli webpack-dev-server
Enter fullscreen mode Exit fullscreen mode
  • webpack
    • Module bundler with the main purpose to bundle JavaScript files for the browser.
  • webpack-cli
    • Command Line Interface (to execute webpack terminal lines).
  • webpack-dev-server
    • Utilize webpack with a development server to provide live reloading.

Now, run the following script:

npm install --save-dev --save-exact html-webpack-plugin style-loader css-loader file-loader
Enter fullscreen mode Exit fullscreen mode
  • html-webpack-plugin
    • Simplifies creation of HTML files to serve your bundles.
    • This plugin is useful when webpack bundles include a hash in the file name. Learn more about the importance of hash here.
  • file-loader
    • Resolves import/require() on a file into a url and emits the file into the output directory.
  • css-loader
    • Interprets import and url like import/require and will resolve them.
  • style-loader
    • Inject CSS into the DOM.

Finally, at the root of the project, create a webpack.config.js file and write the following:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");

module.exports = {
  entry: "./src/index.js",
  mode: "development",
  output: {
    filename: "bundle.[fullhash].js",
    path: path.resolve(__dirname, "dist")
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html"
    })
  ],
  resolve: {
    modules: [__dirname, "src", "node_modules"],
    extensions: ["*", ".js", ".jsx", ".tsx", ".ts"]
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: ["babel-loader"]
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: ["style-loader", "css-loader"]
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        exclude: /node_modules/,
        use: ["file-loader"]
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Entry:
    • Indicates which module webpack should use to begin building out its internal dependency graph. From that entry point, webpack will figure out which other modules and libraries that entry point is dependent on. Learn more about Entry here.
  • Output:
    • Tells webpack where to emit the bundles it creates and how to name these files. Learn more about Output here.
  • Plugins:
    • Plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment. Learn more about Plugins here.
  • Resolve:
    • Changes how the modules are resolved. Learn more about Resolve here.
  • Modules:
    • This field can also be called "Loaders" and allows webpack to process other types of files and convert them into valid modules that can be consumed by your application and added to the dependency graph. This is done because webpack only understands JavaScript and JSON files. Learn more about Loaders here.

Time to Program!

1. Create Hello, World!

Create a folder called "src" with the following files:

  • App.js
const App = () => (
  <div>
    <h1>Hello, World!</h1>
  </div>
);

export default App;
Enter fullscreen mode Exit fullscreen mode
  • index.js
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';

const rootElement = document.querySelector('#root');
if (!rootElement) throw new Error('Failed to find the root element');
const root = createRoot(rootElement);
root.render(
  <StrictMode>
    <App />
  </StrictMode>
);
Enter fullscreen mode Exit fullscreen mode
  • index.html
<!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</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

2. Run program

Now, in the package.json file, add these lines to your scripts section:

"start": "webpack serve --open",
"build": "webpack --config webpack.config.js --mode production"
Enter fullscreen mode Exit fullscreen mode

Command line explained:

  • npm run start
    • Serve will run the webpack-dev-server
    • --open will allow webpack to launch browser automatically
  • npm run build
    • --config webpack.config.js provide path to webpack configuration file
    • --mode production defines mode to pass to webpack

Now in the terminal just run npm run start and you will see your application run!

Bonus!

Script Commands: When running the command npm run build webpack will build the project and create a "dist" folder. This folder will have all of the information that will be sent to the browser for production mode.

Package Management: Every package is currently saved as a dev-dependency. This is done because it is not necessary to send these packages to the client-side since we are going to be transpiling our code to vanilla JavaScript with Babel. The install commands all come with --save-exact in order to keep control of all package versions.

View everything together in Github.

If you found this helpful or just enjoyed reading the article, consider grabbing me a cup of coffee.

💖 💪 🙅 🚩
rinconcamilo
Camilo Rincon

Posted on September 3, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related