DEV Community

The JS Bundle Wars [1/n]

If you're in the JS ecosystem, at some point you'll face this duo: esm & cjs...
are umd & amdstill a thing?

and you'll be like «what is exactly es referencing here?» «do i need es2020 or esnext?»

and if you have an internal library —especially if it’s frontend related–someone on the team will eventually ask:
«Wait, how are the assets/CSS being bundled exactly?»

that's The JS Bundle Wars.

It's a war.
isn't pretty.
isn't easy.

BUT it's interesting as f*


this topic could lead to a complete book (Have I mentioned I dream about writing a dev book and selling it on Amazon?)

Today, I’m just kicking things off...as every complex topic should, with a simple hello world.

I’m not even using React yet, let’s start with a plain Vanilla JS hello world page.

Hello World screenshot

This is the repo im playing with: js-bundle-war


the code is super simple.
We just need an import, an index.html and the <script type="module"> tag.

index.html

index.html

is importing a ES module: main.js

main.js

Which in turn imports other ES modules: app.js

app.js


so far, so good.

I'm using Vite as bundler. I don't want to get back to webpack.

so , if we create a package.json and define how to build this:

 "devDependencies": {
    "vite": "6.3.5"
  },
...
 "scripts": {
    "build": "vite build "
 }
Enter fullscreen mode Exit fullscreen mode

leaving the default vite.config (no config file at all), its' going to bundle this:

default bundle

dist
├── assets
│   ├── index-16Psp_lK.js
│   └── index-CrYBktwj.css
├── index.html
└── vite.svg
Enter fullscreen mode Exit fullscreen mode

which is the real thing. I mean, this is the actual code read/rendered by the browser.


let's open the bundled js shall we?

build-vite

I highlight:

  • An initial IIFE to polyfill modulepreload: this is a Vite-specific detail. Vite uses modulepreload links in the HTML to prefetch JS modules for better performance.
    BUT some browsers might not support modulepreload, so Vite includes a polyfill to make sure the assets are still fetched properly.

  • SOME SVGs are inlined in the build, while others are referenced as external modules.
    (The screenshot was tweaked in this part — let’s take a clearer one to explain it better.)
    The key difference is where we did place the asset:

    • if it’s under /public, it’s served as-is;
    • if it’s inside src/, it gets bundled as part of the code.

focus-on-the-svg

  • Our components, minified.

  • And finally, the last lines: our main.js file.


So, we're building modern ES modules, the bundling process takes our clean, modular code (what we wrote) and outputs the real .js file... which isn't meant to be read by humans but is executed by browsers.

This bundling process handles dependencies, minification, and assets.

...but

why are we even doing this? I mean, ok this is how we bundle , this is the output that is consumed by the browser... why? 🤔


That’s it for today — but this is just the intro, see you in the next article of the series.

Thanks for reading.

Top comments (0)