Webpack Unpacked: The Modern Way to Bundle Assets for your Website
Tags: webpack, javascript, webdev, babel
Published: 2021-10-31 05:06:23

Managing assets can be a cumbersome task. Luckily we now have bundlers to streamline this task. In this article, we would be taking a look at **Webpack**, the most popular bundler available.

**Webpack** can seem extremely daunting at first glance, but this article will ensure that you have enough knowledge to configure **Webpack** on your own. 

![Let's Do It](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rta3rvsvaej9huvrm09s.gif)

# What Exactly is Webpack?

Let's see how Google defines it: _"webpack is an open-source JavaScript module bundler. It is made primarily for JavaScript, but it can transform front-end assets such as HTML, CSS, and images if the corresponding loaders are included. webpack takes modules with dependencies and generates static assets representing those modules."_

You might have come across a few new terms like _"loaders"_ in the definition. Let's take a look at a few terms before proceeding:

- **loaders**: **Loaders** are _third-party extensions_ that help **webpack** deal with various file extensions. For example, there are loaders for **CSS**, for images, etc.

    The goal of a loader is to transform files (other than **JavaScript**) in modules. Once the file becomes a module, webpack can use it as a dependency in your project.

- **plugins**: **Plugins** are _third-party extensions_ that can alter how **webpack** works. For example there are **plugins** for extracting **HTML**, **CSS**, for working with micro-frontends.

# First Webpack App

Let's start small. Initialize a new node project by creating a new folder and using the command `npm init -y`. Install **webpack** related dependencies using `npm i -D webpack webpack-cli`

NOTE: **Webpack** dependencies should always be Dev Dependencies.

Initialize the following files:

```js
// webpack.config.js

const path = require('path');

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

```html
<!-- public/index.html -->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Webpack Demo</title>
  </head>
  <body>
    <script src="../dist/bundle.js"></script>
  </body>
</html>
```

```js
// src/index.html

console.log("Hello Webpack!")
```

Finally, add the following script in your `package.json`:

```json
"scripts": {
    "build": "webpack --config webpack.config.js"
}
```

Now you can use `npm run build` to generate `dist/bundle.js` and run `public/index.html` to utilize the generated bundle.

# Adding Loaders

You might be wondering _"So much work for THIS?"_ Fret not my friend, here's where **Webpack's** magic starts.

Add `file-loader` to our project using `npm i -D file-loader` and update `webpack.config.js`

```js
module.exports = {
    // ...
    module: {
        // defining the rules for additional modules, other than .js files
        // you can very well use rules for .js files too, eg: using babel-loader
        rules: [
            {
                // files the rule applies to (using RegEx is a good practice)
                test: /\.(png|jpe?g|svg)$/,
                // loaders & configuration
                use: [
                    {
                        loader: 'file-loader',
                        // if you skip the options, the default options will be used
                        options: {
                            name: '[name].[ext]',
                            outputPath: 'images/',
                        },
                    },
                ],
            },
        ],
    },
};
```

Now you can import image files into your projects.

```js
// src/index.js

// NOTE: you can use ES Modules import/export statements
import natureImg from './assets/nature.jpg'

const img = document.createElement('img')
img.src = natureImg
document.body.appendChild(img)
```

Run the `build` script to generate the files. Open `public/index.html`

![Page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/978yp5l525dq0hhu7ulu.PNG)

# Adding Plugins

Let's now optimize how we handle **HTML** so that **webpack** automatically adds the script files to the page. Add the `html-webpack-plugin` using the command `npm i -D html-webpack-plugin`.

```js
// webpack.config.js

// ...
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    // ...
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html',
        }),
    ],
};
```

Remove the `script` tag from `public/index.html`. **Webpack** will inject the scripts. It will also generate an additional `index.html` file in the _dist_ folder, which you can use.

# Using Dev Server

Repeatedly reloading the page quite often turns out a big pain. To solve this very problem, we have `webpack-dev-server`.

Install the dependency using `npm i -D webpack-dev-server`. 

```js
// webpack.config.js

// ...
module.exports = {
    // ...
    devServer: {
        port: 3000, // default: 8000
    },
};
```

Finally you need to add another script: 

```json
"start": "webpack serve --config webpack.config.js"
```

You can now use `npm start` to start up the **webpack server**

# Wrapping Up

That's all you need to know about **webpack**... it's just a module bundler, which allows you to configure it as per your requirement using **loaders** and **plugins**. You can look at some other available plugins in the following articles:
- [Create React App from Scratch](https://dev.to/ruppysuppy/create-react-app-from-scratch-like-a-pro-de0)
- [Micro-Frontends: The Next Gen Way to build Web Apps](https://dev.to/ruppysuppy/micro-frontends-the-next-gen-way-to-build-web-apps-16da)

Hope you have overcome your fear of using **webpack** and this article helps you in your development journey!

I am currently working on a project using a completely custom configured **Webpack**, feel free to check it out:

{% github https://github.com/ruppysuppy/Crypto-Crowdfund no-readme %}

Finding **personal finance** too intimidating? Checkout my **Instagram** to become a [**Dollar Ninja**](https://www.instagram.com/the.dollar.ninja/)

# Thanks for reading

Need a **Top Rated Front-End Development Freelancer**? Contact me on [Upwork](https://www.upwork.com/o/profiles/users/~01c12e516ee1d35044/)

Want to see what I am working on? Check out my [GitHub](https://github.com/ruppysuppy)

I am a freelancer who will start off as a **Digital Nomad** in mid-2022. Want to catch the journey? Follow me on [Instagram](https://www.instagram.com/tapajyotib/)

Follow my blogs for **Weekly new Tidbits** on [Dev](https://dev.to/ruppysuppy)

**FAQ**

These are a few commonly asked questions I get. So, I hope this **FAQ** section solves your issues.

1. **I am a beginner, how should I learn Front-End Web Dev?**
   Look into the following articles:

    1. [Front End Development Roadmap](https://dev.to/ruppysuppy/front-end-developer-roadmap-zero-to-hero-4pkf)
    2. [Front End Project Ideas](https://dev.to/ruppysuppy/5-projects-to-master-front-end-development-57p)

2. **Would you mentor me?**
   Sorry, I am already under a lot of workload and would not have the time to mentor anyone.

3. **Would you like to collaborate on our site?**
   As mentioned in the _previous question_, I am in a time crunch, so I would have to pass on such opportunities.

**Connect to me on**

-   [LinkedIn](https://www.linkedin.com/in/tapajyoti-bose/)
-   [Portfolio](https://tapajyoti-bose.vercel.app)
-   [Upwork](https://www.upwork.com/o/profiles/users/~01c12e516ee1d35044/)
-   [GitHub](https://github.com/ruppysuppy)
-   [Instagram](https://www.instagram.com/tapajyotib/)