Skip to content
JavaScript Bundling ELI5

JavaScript Bundling ELI5

Let's see, so we know that we can include JavaScript scripts into a web page using the script tag. But what if we need to include a module script? Wait, I think I need to explain first what a module script is!

Classic Script vs Module Script

Let's say we have a main.js file containing the following code:

const squareArea = side => side * side;
const squarePerimeter = side => 4 * side;
const rectangleArea = (l, b) => l * b;
const rectanglePerimeter = (l, b) => 2 * (l + b);
 
const side = 2;
const len = 2, breadth = 2;
const shapes = ['square', 'rectangle'];
 
for (let shape of shapes) {
  console.log(`${shape} Area and Perimeter`);
  switch (shape) {
    case 'square':
      console.log(squareArea(side), squarePerimeter(side));
      break;
    case 'rectangle':
      console.log(rectangleArea(len, breadth), rectanglePerimeter(len, breadth));
      break;
  }
}

This file can be called a classic script and can be added to our web page with script tag.

But what if we decide to modularize and move each shape related logic into their corresponding files? Then we would have to import each file into the main file, like so:

// square.js
export const area = side => side * side;
export const perimeter = side => 4 * side;
 
// rectangle.js
export const area = (l,b) => l*b;
export const perimeter = (l,b) => 2*(l+b);
 
// main.js
import square from "./square";
import rectangle from "./rectangle";
 
// rest of the code in main...

Now we can call the files square.js and rectangle.js as modules. Since the main file now imports modules, we can't add this file as a classic script anymore, but rather only as a module script.

Including modules via <script>

We can include a module script via script tag like so:

<script type="module" src="main.js"></script>

All module scripts are defer by default, which means the script is fetched asynchronously while the HTML is parsed. But the module is evaluated only right before the parsed HTML is loaded as DOM content.

Limitation with <script type="module">

Although this is the modern browser age, it's quite possible that there will be some backward compatibility issues with older browsers which don't support the attribute value type="module", as it's relatively new.

Another known limitation is that unused code from the imported modules are not removed. They are imported, or let's say fetched as part of the module by the client over internet, even though they are useless.

When to bundle?

Ruby on Rails version 8 by default serves modules without any bundling or minification. DHH(creator of Rails) points out that even hey.com (opens in a new tab) doesn't use bundling, and thus it's unnecessary.

The limitation that we had previously mentioned, where even unused code is sent to the browser on request, won't be an issue if let's say the number of modules is less than 100. Fetching these many number of modules in the browser would be fast enough that the client doesn't notice any delay.

But, if the project is massive, where we are serving a lot of modules, obviously greater than 100, then we need to first measure the performance of the web page and see how much of an impact this limitation has on it. If it's significant, then bundling is a very good option to consider!

Bundling in simple terms

What a bundler does is, it goes on a hunt for the dependencies, which are modules required by the entry point JavaScript file. It does this process in a depth-first-searching manner, and then dumps all the required module functions/variables into a single file(here it will the main.js). This final product is the bundle.

A bundler also bundles linked CSS and/or other objects necessary to make the web page run. It makes use of loaders to transform the data into required JavaScript understandable objects.

A bundler can also minify the code, where it removes unnecessary characters like whitespace, comments, semicolons etc. Minification can help the webpage load faster.

It also does dead-code elimination where unused functions/variables etc are removed from the JavaScript delivered to client.

Bundling can be done by any of the available bundlers in the market, like say webpack, esbuild etc.

References