What Is A JavaScript Bundler?
Tags: programming, javascript, roadtodotnetfullstack, webpack
Published: 2023-09-02 08:57:38

---
title: What Is A JavaScript Bundler?
published: true
date: 2023-09-02 08:16:11 UTC
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vmynu2us9tqp0bhbmg7.jpg
tags: Programming,javascript,roadtodotnetfullstack,webpack
canonical_url: https://www.codejourney.net/what-is-a-javascript-bundler/
---

If you asked me 5 years ago what a JavaScript bundler is, I’d probably tell you it’s something people fight with for hours, just to get a simple web app set up 🤪 While this might have been closer to the truth in 2018, a lot has changed in JavaScript ecosystem until today.

If you’re starting your web development journey, or maybe have already dived into it, but are not really sure what JS bundlers are and what’s their role, you’re reading a proper piece of explanation 🙂

## Chaos and complexity – the issues

Let’s consider a very simple JavaScript app. We have just one page `index.html`. Our HTML is hydrated with `index.js` file, which adds some interactivity to it. In order to use it, we need to import `index.js` script in `index.html` file. We also decided to use an external library (Bootstrap), so we should also link the necessary CSS.

We are linking the `index.js` with a `script` tag in `head` section:

 
```html
<head>
    <script type="module" src="index.js"></script>
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
      crossorigin="anonymous"
    />
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My WebPage</title>
  </head>
```
 

Of course, as we are building a web application, we won’t put all the JavaScript code in `index.js`. That’s why we created two separate files with some functionalities: `my-utils.js` and `navigation.js`.

For instance, the `my-utils.js` exports a few functions:

 
```js
export function doSomethingNice() {
  alert("Nice!");
}

export function notUsedFunctionA() {
  alert("Not used function A");
}

export function notUsedFunctionB() {
  alert("Not used function B");
}

export function notUsedFunctionC() {
  alert("Not used function C");
}
```
 

Notice the not used functions there – we’ll get to the point of them soon.

Next, our `index.js` file imports what it needs and adds some interactivity to the HTML elements:

 
```
import { doSomethingNice } from "./my-utils.js";
import { reloadThePage } from "./navigation.js";

document
  .getElementById("reload-page-btn")
  .addEventListener("click", reloadThePage);

document
  .getElementById("say-sth-nice-btn")
  .addEventListener("click", doSomethingNice);
```
 

If we now open our webpage, we can see the network activity when the page is loaded:

![HTML page loading JavaScript files](https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/08/html-loading-javascript-1.png?resize=1131%2C330&ssl=1)

Notice that all 3 JavaScript files are fetched separately: `index.js`, `my-utils.js` and `navigation.js`.

What’s more, if you check the contents of `my-utils.js`, it obviously loads the whole script, containing even the not used functions:

![HTML script file content](https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/08/html-utils-fetching-content.png?resize=558%2C300&ssl=1)

I think you might already feel that this can get a little problematic 😉 Imagine managing this when you have hundreds of your own JavaScript files plus dozens of external libraries. Not only will your app be making hundreds of network requests to fetch every single file, but it will always fetch everything – even the stuff your page doesn’t use.

Here’s where a JavaScript bundler comes into the field.

You can find full source code of this JavaScript app [here](https://github.com/dsibinski/codejourney/tree/main/javascript-bundlers/no-bundler-app).

## What does a JavaScript bundler do?

JavaScript bundler produces _bundles_ 🙂 But what is a bundle? It’s basically a static file, optimized to be served to the client (in our case: a web browser). The main goal is to produce a single bundle file from multiple dependencies. In effect, the user’s browser doesn’t need to fetch so many files separately. But how is such a bundle created?

First, a JavaScript bundler needs to know the _entry point_. It’s a kind of root in which our “code tree” begins. In the case of our sample JavaScript application from the previous paragraph, a perfect candidate for an entry point would be the `index.js` file. Modern bundlers support multiple entry points. It can be very useful if you’re building a multipage application, so each page can have its own entry point.

The next step is to create a dependency graph. The JavaScript bundler is basically starting from the root (entry point) and traverses all dependencies referenced from it, as well as all of these dependencies’ dependencies. Having the dependency graph, bundler knows what is exactly used by what and in which place of our app.

This is how you can imagine the graph of dependencies:

[![webpack - graph of dependencies](https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/08/webpack-dependency-graph.webp?resize=858%2C348&ssl=1)](https://paulallies.medium.com/webpack-managing-javascript-and-css-dependencies-3b4913f49c58)

Module bundlers like [webpack](https://webpack.js.org/) not only know the dependencies of your entry point. These tools even check what each dependency uses. Thanks to building such a detailed dependency graph, the bundler can introduce multiple optimizations into the bundle file.

Finally, JavaScript bundler outputs the actual bundles. As I mentioned, bundles can be highly optimized by applying techniques like [code splitting](https://webpack.js.org/guides/code-splitting/), [CSS inlining](https://vitejs.dev/guide/features.html#css), [HMR](https://parceljs.org/features/development/#hot-reloading) and various performance optimizations.

JavaScript bundler might also ensure the backwards-compatibility with older web browsers by converting some newer JavaScript constructs used in your code to their equivalents from previous JS versions.

What’s interesting, modern bundlers can handle not only JS files, but also CSS, HTML and even images.

## JavaScript bundler in action

Currently, the most popular JavaScript bundles is (still) [webpack](https://webpack.js.org/). It has been the first really advanced bundler created for both the browser and NodeJS.

You might have heard unpleasant things about webpack and in fact, its configuration can get really _spaghetti_ 🤪 There are simpler alternatives out there, but let’s start with what’s the most common tool used in web development today.

### Adding webpack to a JavaScript app

Our sample app already has a `package.json` file (we used JavaScript modules), so we can install webpack with this command:

```
npm install --save-dev webpack webpack-cli
```

Now we should reorganize the files a bit. Let’s put all scripts in `src` folder and move `index.html` to `dist` folder. Finally, it looks like that:

![Webpack app structure](https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/08/webpack-app-structure.png?resize=241%2C217&ssl=1)

Using the folder named `dist` is very common. It stands for _distributable_, which means the code ready to be distributed = served to the public. This is where our bundles will be located. As the `index.html` is directly served to the public, we also place it there.

With such a folders structure, there’s nothing more we need to configure for webpack to work. By default, webpack looks for `src/index.js` file which we already have and outputs bundles into the `dist` folder. To use more advanced features or multiple entry points, a [configuration file should be added](https://dev.to/godspowercuche/6-ways-to-configure-webpack-28k4-temp-slug-4390628).

In our case, let’s go with the zero-config approach. The only thing we need is to add a `script` entry to `package.json`:

 
```json
 "scripts": {
    "build": "webpack",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
```
 

Let’s now run `npm run build` and see what happens:

![Webpack build output](https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/08/webpack-build-output.png?resize=483%2C154&ssl=1)

It seems that webpack created the `main.js` asset (bundle):

![webpack main bundle](https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/08/webpack-main-bundle.png?resize=351%2C245&ssl=1)

Let’s make sure that our `index.html` page links this bundle file properly:

 
```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script type="module" src="main.js"></script>
```
 

Now, let’s open our `index.html` page and see how the network requests look like now:

![webpack app - network activity fetching bundles](https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/08/webpack-app-bundle-fetching-network.png?resize=1138%2C283&ssl=1)

Wow, that’s something different from what we had previously! Notice that now only 1 script, the `main.js` file, is fetched by the webpage. There were 3 before: `index.js`, `my-utils.js` and `navigation.js`. Of course, the web page works exactly as before.

Let us also examine the contents of the fetched `main.js` file:

![webpack app main.js bundle content](https://i0.wp.com/www.codejourney.net/wp-content/uploads/2023/08/webpack-app-main-bundle-content.png?resize=942%2C248&ssl=1)

Pay attention what happened here. Webpack has nicely inlined all the external code we used directly into the `main.js` bundle. What’s more, the exported, but not used functions from `my-utils.js` are not present here at all! When building the dependency graph, webpack noticed that those functions are not used, so it didn’t include them 😉

This is basically how webpack and most JavaScript bundlers work. Their role is to deliver the smallest and the most optimized bundles possible. This ultimately saves a lot of bandwidth by avoiding unnecessary network requests the client browser would otherwise need to make. Cutting out the unused code makes the bundles smaller, again reducing the network usage.

You can find full source code of the webpack app [here](https://github.com/dsibinski/codejourney/tree/main/javascript-bundlers/webpack-app).

### Webpack has a lot more to offer

From all the JavaScript bundlers used today, webpack is the most advanced one. It’s the most mature one as well. It offers dozens of customizations, [plugins](https://webpack.js.org/concepts/#plugins) and [loaders](https://webpack.js.org/concepts/#loaders). You can also easily add [TypeScript](https://www.codejourney.net/is-it-worth-migrating-to-typescript/) support.

You can do really crazy stuff with webpack 😉 However, if you are starting your web development journey, don’t get overwhelmed by learning it all. Just be aware that webpack can do almost everything you might need. It’s just a matter of [searching StackOverflow](https://stackoverflow.com/questions/tagged/webpack) or asking [Copilot](https://github.com/features/copilot) 😉

### Alternatives to webpack

In recent years, developers created a few other amazing JavaScript bundlers. I recommend you to pay attention to them, because webpack doesn’t have to be your first choice today. Webpack is still [used in CRA](https://create-react-app.dev/), which is believed to be a default way of creating new React applications. This is what makes it very widely used, but you don’t need to follow this path 🙂

I recommend checking [Parcel](https://parceljs.org/), [esbuild](https://esbuild.github.io/) and [ViteJS](https://vitejs.dev/). These are modern bundlers created to, among others, eliminate some of webpack’s burdens. If you’re starting out and don’t want to get yourself busy with bundling configuration, I especially recommend creating your next app with Parcel.

## Summary

That’s all that you need to know about JavaScript bundlers to be able to work with them and understand what’s happening when executing this magic `npm run build` script 😉

The post [What Is A JavaScript Bundler?](https://www.codejourney.net/what-is-a-javascript-bundler/) appeared first on [CodeJourney.net](https://www.codejourney.net).