How to setup React with Webpack

For beginners who’ve always wanted to build a React app without using create-react-app

Sandesh Chapagain
Level Up Coding

--

Webpack Logo

Create-react-app has made all of our lives easier, and is definitely a great tool to quickly start building a React application. However, have you ever wondered what might be involved in making such an app from scratch?

I have always used CRA for my own hobby projects, but was recently handed over an application that had a custom webpack configuration. This gave me a great opportunity to learn some of the webpack fundamentals before I dove into the project, and started contributing.

Webpack has a lot of features, and the documentation, albeit helpful, can be very overwhelming. I spent hours and hours browsing the docs, and also watched a lot of instructional videos on YouTube. Here, I wanted to document and share what I learned, and I hope anyone in a similar boat will find this useful.

Initialize the Project

First things first, lets create an empty project, and install a few dependencies. Create a directory, and run

npm init -y

to initialize your new project. That should create a default package.json manifest file.

Please feel free to omit the -y flag, and initialize the project however you want.

Now lets install some basic packages we’ll be using:

  • react — the main react library
  • react-dom — package that allows us to use react in the browser
  • webpack — the JavaScript bundler we’ll be exploring more below
  • webpack-cli — tool that allows us to run webpack commands from the command line.

To install all of them run the following commands:

npm i react react-dom
npm i -D webpack webpack-cli

Notice that webpack and webpack-cli are installed as dev-dependencies since we only need them during development. The only runtime packages in this entire tutorial will be react, and react-dom.

Setup the Project Structure

At this point, you should already have package.json and package-lock.json files in your root directly. Now create a few empty files, which we’ll be populating later, and setup your project so that it mimics the directory structure shown below:

Learn Basic Webpack Terminologies

Before we dive into configuring webpack, and making our little application, lets learn a few things about webpack.

webpack is a JavaScript code bundler that traverses the dependency graph of your project (chain of imports you use in your JS files), and creates a static JavaScript file(s) that is ready to be attached to your HTML.

There are a couple of terminologies regarding webpack that must be introduced before we start playing with it:

  • Entry — This is the top of the dependency tree (conventionally src/index.js) where webpack starts with the bundling process.
  • Output — The output file(s). AKA the bundle.
  • Loaders — webpack, by default, only works with JavaScript files, but we obviously want to be able to import other file types(CSS, JSX, etc.). This is where loaders come into play. They are packages (not included with Webpack itself) that help us import non-JavaScript files directly into our JavaScript.
  • Plugins — Plugins are also other third party packages that can be used with webpack to extend it’s functionality. There are a lot of plugins out there, but here, we’ll only be dealing with the html-webpack-plugin. More on this later.

Create a Minimal React Application

That’s pretty much all we need to know about webpack to get started. Now lets go ahead a fill those files we created earlier with some code so we can test things out on the browser.

I assume you guys are familiar with React, and won’t explain React code in this article.

All this application is supposed to do is to render a heading tag, which spits out ‘Hello World’ to the page. However, if you try and attach index.js directly to your HTML with

...
<script src="index.js" />
</body>
</html>

it doesn’t work. If you open it up in the browser, all you’re going to see is a blank page.

This is because the browser does not know how to import App from “./App”. Only static JS files can be loaded by the browser, so lets finally configure webpack to convert our application into something that the browser can understand.

Install Loaders

Let’s first install babel-loader that allows us to compile JSX into browser compatible JavaScript. To do so, run the following:

npm i -D @babel/core @babel/preset-env @babel/preset-react babel-loader

What we did was install babel, two presets, and then finally the loader required to load our JSX files. Please explore babel’s docs to learn more about what these presets do.

Configure Webpack

Now we’re ready to ask webpack to kindly use Babel during bundling to understand any JSX files.

Entry and output should be clear from our discussions above, but what is module.rules?

From the docs, it is:

An array of Rules which are matched to requests when modules are created. These rules can modify how the module is created. They can apply loaders to the module, or modify the parser.

In our config file, we asked webpack to use babel-loader, whenever it sees any file ending in either js or jsx. To learn more about how regular expressions (/\.(js|jsx)$/ above) work, please check this out.

Bundle the Application

Now let’s add a script to our package.json so we can easily build our application whenever we want to.

Please feel free to run webpack-cli from the command line. I added a script so that if you wanted to add different scripts for development, production, staging and whatnot, and maybe add modes to your scripts, you’ll now know how, and where.

Finally we’re ready to run

npm run build

If you’ve been following me along exactly, then this should create a main.js file inside the dist folder in your project root. We can now go ahead and attach this bundled JavaScript into our html.

Run the Bundled Application

After adding the script tags as suggested above, open up your index.html in the browser, and voila, you’ll see “Hello World”! That’s it. You’ve bundled your first application. Easy, right?

Setup HtmlWebpackPlugin

Attaching the bundled JS manually, like we did above, is all good and fine, and if all we would ever have is one JavaScript file in our bundle, we’re good to stop here. But in a real application, you’ll be using various webpack plugins to chunk your JavaScript files, and maybe even hash them for caching purposes. All this means, is that we don’t want to manually import our bundle scripts into our HTML.

To automate that process, let’s install html-webpack-plugin using the following command:

npm i -D html-webpack-plugin

Now we modify our configuration file to include this plugin as such:

What we did was include the plugin and provided it with a template html to which webpack is to attach the bundled JavaScript after the build.

You can go ahead and remove the <script> tag from your src/index.html. Now if you run

npm build

you’ll notice that not only is main.js created inside the dist folder but also an index.html — with main.js automatically included!

What’s Next?

You might have noticed that we didn’t do anything with our ‘index.css’ file. I wanted to leave that one as an exercise for you guys. Look up style-loader and css-loader, and see if you can import index.css into your App.js file. The process is very similar to how we used babel-loader. You need to first write a test to filter out only .css files, and then use both the style, and the css loader.

I took this a step further, and configured my application with webpack-dev-server. You can find the finished project in my github. To start the dev server, simply run (after you do npm install, of course):

npm run start

Since the dev-server is setup with hot reloading, you no longer need to refresh the browser after you make any changes to your application.

Thanks for reading!

--

--