Create React App is the first choice of most, if not all, React developers. It creates a React project for us and only requires a few commands. Its simplicity and quick nature make it a favorite among beginners as well. But, there are also ways to create a React app without it.
One of these ways is using a module bundler like Webpack and a compiler like Babel.
By the end of this article, you will have your very own React app without using
Since this React app will use the Webpack module bundler, we need to install quite a few dependencies. These dependencies are required by Webpack so it can detect and work with the various file types.
Here's what we need to install:
These two packages are the dependencies we need for our simple app. If your project needs any other packages, you may install those.
There are close to 10 devDependencies, so let's install them in groups and I'll explain what each dependency is for. First comes webpack:
webpack: Installs the webpack module bundler
webpack-cli: Offers a variety of commands that make it easier to work with webpack on the command line
webpack-dev-server: Allows us to use a simple web server with hot reload
Next, we'll install Babel:
@babel/core: Core package for the Babel compiler
babel-loader: A plugin that enables Webpack to work with Babel and its presets
The remaining devDependencies are for CSS and HTML:
css-loader: Required so that webpack can detect
html-webpack-plugin: Generates an HTML file that includes all your Webpack bundles via
Everything a basic React project needs is installed. Now create these folders and file in the project's root:
publicfolder for the HTML file and assets (images, fonts, etc.)
.jsfiles and React components
babel.config.jsonBabel configuration file
At this point, your project folder should look something like this:
Let's add the presets in the Babel config file:
It is recommended to have two separate config files for Webpack - one for development and one for production. Although both files will have the same configuration for loaders and any plugins, there are slight differences. This is what a config file for development looks like:
Here, we first declare the
mode configuration option. With this, Webpack can use its built-in optimizations accordingly. Next,
module.rules is an array containing 3 objects:
- This rule tells Webpack to look for files ending in
.jsand use Babel to compile them.
babel-loaderhelps Webpack work with Babel.
- The second rule tells Webpack to look for files ending in
.cssand make sense of them with the help of two loaders -
- The last rule helps Webpack recognize image files. There is no need to install any external loader for this.
Note: According to the Webpack docs,
css-loaderneed to be used in the exact same order as in this config file or it won't work.
html-webpack-plugin. This plugin tells Webpack to use our HTML file as a template and inject the compiled bundles into it.
So, instead of creating its own HTML file, Webpack instead uses our HTML file -
public/index.html and adds the bundled files to it via
The other plugin we use is
HotModuleReplacementPlugin which comes with the webpack package and is used for hot reloading our app in development mode.
devServer object contains options used by
Now let's take a look at the production version of the configuration file:
Not much has changed except that we no longer need
devServer since they will not be used in production. The
mode option has also been set accordingly. You might have noticed the changes in
output.filename has a value that we haven't seen before. The values in square brackets are tokens. The
[name] token allows Webpack to name files differently if we use code-splitting.
[contenthash] is used so that the bundle file name changes when its content changes.
Our app is almost ready. I have a simple
The app looks like this now:
Finally, we need to add scripts to run our app:
serve option Webpack uses
webpack-dev-server to create a web server. Let's run our app.
https://localhost:8080 in your browser and your app should be running.
This is a basic React app where we manually configure Webpack. I hope this helped you to understand a bit about the various plugins and loaders Webpack requires and what its configuration files look like. The Webpack documentation is worth reading. It was the major resource I used for this article.
Here are links to some additional resources:
- Webpack documentation on config files and the various options a config file can have
- Webpack documentation on loading CSS and other assets
- Webpack documentation on webpack-dev-server and html-webpack-plugin
- An article from Carl Rippon on creating a React app that uses TypeScript and ESLint with Webpack 5
- Babel documentation on its config files