[React] How to configure Webpack

Introduction

While implementing a React app for this chat application, I ran into some problems setting up a proxy to call APIs provided by the backend. Most of the times adding a proxy to package.json did the job for me. If this didn’t work out for me for some reason, then I used http-proxy-middleware to configure my proxy. This was the furthest I could go because I did not want to look into the complex configuration of webpack or other alternatives. I always wanted to focus more on the implementation. However, this time with that chat application, I came across a situation where http-proxy-middleware or proxy worked out for me. This motivated me to learn how to configure webpack and webpack-dev-server.

Webpack

Webpack is a static module bundler for modern Javascript applications. Let’s look at some core concepts to figure out how to configure it.

https://webpack.js.org/

Webpack Core Concepts

Entry

  • The entry object is where webpack looks to start bundling. Webpack will build internal dependency graph to figure out which other modules and libraries that entry point depends on.
  • Default value: ./src/index.js
  • Consideration: One entry point for SPA, multiple for MPA (one entry point per HTML page).
  • In this example, we can use the default value since index.js renders the React App to the root div.

Output

  • The output object defines where webpack should output bundles and assets.
  • Default value: ./dist/main.js.
  • In this example, I will set the output as dist/app.[contenthash].js. I added a unique hash for caching. This will help loading the site faster. For picking up the new code after a new deployment, let’s see how plugins can help with caching.

Loaders

  • Because webpack only understands JavaScript and JSON files, module object can be used to define loaders to process other types of files (css, jsx, tsx, etc)
  • An array of rules can be set in module.rules to modify how the module is created. Each rule can basically test the conditions and use the specified loader.
  • Loaders work with the individual files during or before bundling.
  • In this example, I will define 2 rules. First of all, I need webpack to handle the css files for styling. Secondly, I need webpack to transpile js and jsx files. Let’s look at the sample code after looking into Babel.

Plugins

  • Plugins are additional customizations to perform on the resulting bundle.
  • Plugins work at bundles or chunks at the end of bundle generation process.
  • In this example, I will use HtmlWebpackPlugin to help generating HTML files for the webpack bundles. I mentioned caching earlier during the output section. Using this plugin is very helpful because webpack will include the unique hash that was generated earlier into index.html. This will ensure new code to be picked up.
  • Additionally, I will use two other plugins. We will dive into the sample code after explaining some dependencies.

Mode

  • mode configuration tells webpack to use its built-in optimizations according to the assigned value.
  • Default value is production and possible options are none, development, and production.
  • In this example, I will set the mode on the fly in start and build commands. This could be useful when defining the API URL for different environment.

Before diving into the full webpack.config.js, let us look at some required dependencies.

Dependencies

Webpack

First of all, we need these two dependencies to run npm run start and npm run build commands defined in package.json. Notice how mode is set in the command.

package.json scripts part

Installation

$ npm install --save-dev webpack-cli webpack-dev-server

webpack-cli

webpack CLI provides set of commands to run on terminal.

webpack-dev-server

webpack-dev-server provides a development server. It creates the bundle in memory and serves with express. Express server creates a websocket connection between the bundle and the running port. Therefore when the entry point changes as development goes on, new code will be picked up and the browser refreshes automatically. It can be launched with webpack serve command.

Webpack Plugins

Installation

$ npm install --save-dev clean-webpack-plugin html-webpack-plugin webpack-manifest-plugin

CleanWebpackPlugin

clean-webpack-plugin removes all files under output.path and all unused assets after every successful rebuild.

HtmlWebpackPlugin

html-webpack-plugin simplifies creation of HTML to serve the resulting webpack bundles.

WebpackManifestPlugin

webpack-manifest-plugin generates manifest.json file.

Let us see how these plugins can be used in webpack.config.js.

There are so many more plugins that can be used with webpack. I just listed a few that I think might be useful in any project.

Babel

Installation

$ npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader

Another important part in this webpack configuration is to compile modern JavaScript and React JSX syntax into a backwards compatible version of JavaScript that can be run on current and older browsers. This can be done using Babel.

Babel Core

@babel/core provides the Babel compiler core.

Babel Presets

Babel provides presets that acts as a sharable set of Babel plugins. Basically, applying plugins enable Babel’s code transformation. We are going to use two presets: @babel/preset-env for compiling ES6 syntax and @babel/preset-react for React.

babel-loader

To use the two Babel Presets mentioned above, we need to add babel-loader to the list of webpack modules.

These babel presets and plugin can be defined under webpack.modules.

Setting up DevServer

We covered a lot of background and core concepts of webpack thus far. Let’s go back to our original goal … how to set up a DevServer.

DevServer

Options for webpack-dev-server can be defined under devServer. Basically, all I wanted to do here was to set up proxy and disable compression.

With this setup, HTTP requests going to localhost:3000/api/path/to/endpoint is proxied and rewritten to localhost:8080/path/to/endpoint.

Conclusion

Here are my final webpack.config.js.

webpack.config.js

By running npm run start, I was able to start the webpack-dev-server to run my app locally.

Running npm run build generates the bundle under dist. Just like how I configured webpack, I can verify these results.

  • JavaScript file is generated based on my React code and has a hash in the file name.
  • index.html is generated and includes the generated JavaScript file automatically.
  • manifest.json is generated.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store