6 Webpack Concepts for Advanced React Developers
Tags: react, javascript, programming, learning
Published: 2023-06-30 17:27:32

_**To read more articles like this, [visit my blog](https://www.mdfaisal.com/blog)**_




More often than not, we use `create-react-app` for scaffolding a new React application and call it a day.

But under the hood, a lot of libraries are working to ensure everything just works. And **[webpack](https://webpack.js.org/)** is the most important of them.

Today, we will take a deep dive into webpack and try to understand the different parts of webpack that are relevant to **React development**.

## What’s the Problem?

We know that our browsers don’t understand anything but HTML, JavaScript, and CSS. So the obvious questions are.

* How our browsers understand other files like `.jsx`

* How are all the different files loaded into the browser?

* How our application is bundled?

* How we can optimize them?

## Webpack to the Rescue

Webpack is here to save the day for us! It’s the most popular bundler out there and for obvious reasons!

What **webpack** does is convert everything into **browser-readable** files that are nicely depicted in the following image:

![Source: [webpack](https://webpack.js.org/)](https://cdn-images-1.medium.com/max/5056/1*b5saGFapuUCZx9vSU19mpQ.png)

## Why Should You Care?

Most of the time you wouldn’t. But the knowledge of webpack can help you in some advanced cases:

* Scaffold an application from scratch

* Performance optimization

* Implement micro-frontends

Generally, having an overview of the bundling process makes you more confident about your craft and understand bugs in a production system.

## How Webpack Works

Typically, webpack is configured through a file named `webpack.config.js`. This is where we can configure everything!

Let’s start with a simple configuration file and try to understand its various pieces.

### Example

The following is a very simple configuration file for webpack:

```js
const path = require('path')

module.exports = {
  
  entry: path.resolve(__dirname, 'src', 'index.js'),
  
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  }
  
}
```

Let's talk about `entry` and `output`.

## 1. Entry

`entry` is the entry point of your application. This is the place where webpack starts its journey. We know that our React applications are like a tree. All the components span out from `App.js`.

![Photo by the author.](https://cdn-images-1.medium.com/max/2000/1*N7I3ik50EHDisWCN33qVYw.png)

But where does our `App.js` live? It lives inside the `index.js` file, and that’s why webpack enters into the application via `index.js` and creates a dependency graph to determine which files are needed to be loaded first.

## 2. Output

This is another easy concept to understand. After all the work is done, webpack creates a bundle file. In `output`, we can specify the **name** and the **location** of the output file.

It has also other uses too. If you want to generate dynamic bundle names for the production system for version management you can do that here!

Let's take this a step further and try to understand how our **.jsx** or **.css** files are handled.

## 3. Loader

Loaders are a very important concept in webpack. They are like compilers. Webpack checks for a certain type of file and uses appropriate loaders to handle them.

A typical configuration of the `loader` can be like the following:


```js
module.exports = {
    entry: { ... as before}
    output: { ... as before },
    
    module: {
        rules: [
            {
                test: /\.[jt]sx?$/, // matches .js, .ts, .jsx and .tsx files
                use: ['babel-loader'],, // uses babel-loader for the specified file types
                include: path.resolve(__dirname, 'src'),
                exclude: /node_modules/,
            }
        ],
    }
}
```


Now, look at the `module` part. It takes an array of rules. Each rule has several parts:

* `test` -> It checks for a certain file type. It uses regular expression.

* `use` -> It specifies the list of loaders used for this particular file type.

* `include` -> Which files should be processed.

* `exclude` -> Which should not be processed.

Sometimes we need more than one type of loader for a specific file. A good example is loading CSS files. The rule for that is:


```js
{
    test: /\.css$/, // matches .css files only
    use: ['style-loader', 'css-loader'],
},
```

Here, both `css-loader` and `style-loader` are used to process the file. One important thing to note here is these loaders are loaded in the reversed order.

That means first the `css-loader` will work and then `style-loader` will work on the output produced by `css-loader`.

Similarly, for our `.scss` files:

```js
{
  test: /\.scss$/,
  use: ['style-loader', 'css-loader', 'sass-loader']
},
```

## 4. Plugins

Plugins are another very important aspect of webpack. Plugins are the main reason why webpack is so powerful.

Plugins are like libraries. They can tap into any stage of the compilation process and do whatever they wish.

```js
const {CleanWebpackPlugin} = require('clean-webpack-plugin')

module.exports = merge(common ,{
    entry:  {...},
    output: {...},
    module: {...}
    
    plugins: [ new CleanWebpackPlugin() ]
})
```


In the example above, we used a plugin named `clean-webpack-plugin`. What this plugin does is clean the output folder each time we run our build command.

There are lots of plugins that you can take advantage of. You can refer to [webpack’s official website](https://webpack.js.org/plugins/) if you are interested.

## 5. Mode

This is a simple concept to understand. You would want to use a different setup for your development and production. For this, you can use `mode`.

```js
module.exports = merge(common ,{
    entry:  {...},
    output: {...},
    module: {...},
    plugins:{...},
    
    mode : 'development' or 'production'
})
```


If you set the mode to `production`, then your output bundle will be minified and optimized.

## 6. Development Server

This is the final setup for your application. While developing the application, you will not want to compile it every time you change something. That’s why you need a `devServer` setup for your application.


```js
module.exports = merge(common ,{
    entry:  {...},
    output: {...},
    module: {...},
    plugins:{...},
    mode :  {...},
    
    devServer: {
        contentBase: path.join(__dirname, 'public/'),
        port: 3000,
        publicPath: 'http://localhost:3000/dist/',
        hotOnly: true,
    },
})
```


Now this setup will serve your application from the `dist` that you set up earlier as your `output`.

## Conclusion

There you go. Now you should have a basic understanding of webpack and its different parts. Here is a full setup if you are interested:

```js
const path =  require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
    entry: path.resolve(__dirname, 'src', 'index.js'),
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'bundle.js'
    },
    mode: 'development',
    module: {
        rules: [
            {
                test:  /\.[jt]sx?$/,
                use: ['babel-loader'],
                exclude: /node_modules/,
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.scss$/,
                use: ['style-loader', 'css-loader', 'sass-loader']
            },
            {
                test: /\.html$/,
                use: ['html-loader']
            }
        ]
    },
    plugins: [new CleanWebpackPlugin()],
    devServer: {
        contentBase: path.join(__dirname, 'public/'),
        port: 3000,
        publicPath: 'http://localhost:3000/dist/',
        hotOnly: true,
    }
}
```


Have a great day!

**Have something to say? Get in touch with me via [LinkedIn](https://www.linkedin.com/in/56faisal/) or [Personal Website](https://www.mdfaisal.com/)**