What is a Frontend Bundler (Module Bundler)? Why Use One?
December 6, 2025
In What is a Frontend Build Tool? Why Use One?, we discussed how module bundling is an important part of modern frontend build tools (if you're unsure about the distinction between build tools and bundlers, we recommend reviewing that article first).
In the previous article, we touched on why modern frontend development needs build and bundling tools: to balance developer experience with code optimization.
Code that's easy for developers to maintain doesn't necessarily mean it's optimal for machines. For example, most JavaScript development teams choose TypeScript to reduce errors and improve maintainability. However, browsers can't process TypeScript directly, so we need tools to transform TypeScript into JavaScript that browsers can handle.
Similarly, most frontend teams wouldn't write minified code like this, yet from a machine's perspective, this code works just as well and requires less transmission time due to its smaller size.
function calculatePositiveSum(n) {
let t = 0;
for (let r = 0; r < n.length; r++) {
const c = n[r];
if (c > 0) t += c;
}
return t;
}
Since ideal code for developers and machines differs, we need tools to bridge this gap. The previous article covered build tools conceptually; this one focuses specifically on bundling within the build process. We'll discuss what bundling is, how it works in detail, and why it matters.
The Evolution of JavaScript Modules
Before discussing module bundlers, let's clarify what we mean by "bundling"—more precisely, "module bundling." To understand this, we should review JavaScript's module system evolution and understand what exactly gets bundled.
In software, a module refers to "code with clear boundaries that can be maintained independently and reused." We discussed module design concepts in detail in another article; the key idea is organizing code into separate files and reusing them through export and import.
However, export and import syntax, while standard today, shouldn't be taken for granted. JavaScript, written in just 10 days, didn't originally have native module support.
Initially, if you wanted to split JavaScript across files, the simplest approach was to add multiple <script> tags to your HTML. But this created obvious problems. All scripts became global, risking naming conflicts. If two scripts defined the same variable, they'd interfere with each other.
To solve this, the community developed open-source packages that led to different module standards. In 2009, when Node.js emerged, it adopted CommonJS (CJS), using module.exports and require for module export and import. Even today, older Node.js codebases use this syntax.
However, CommonJS has drawbacks for browsers. It's synchronous, meaning the browser waits for modules to load before continuing. If many modules load this way, the browser can freeze for extended periods. So browser-side developers preferred Asynchronous Module Definition (AMD).
Finally, in 2015, ES6 introduced native module support: ES Modules (ESM), which is the export and import syntax we know today. This allows developers to simply import debounce from 'lodash' without reinventing the wheel.
What is Bundling? Why is it Important?
Having discussed JavaScript's module system, you might ask: why bundle at all if we have ESM? Let's first understand what bundling actually is.
Module bundling means combining different modules together—essentially converting multiple JavaScript files into fewer files.
Consider importing lodash's debounce function into a web app. Though developers don't need to write debounce themselves, browsers still need the actual code to run it.
Browsers don't directly download from npm, so how do they get the code? Bundling solves this. When a page uses external dependencies like lodash, the bundler combines lodash's code with your code into a single output file (like bundle.js), so the browser has everything it needs in one file.
Why Bundling Matters
You might wonder: why combine files if modularity improves the developer experience? Technically, you could avoid bundling altogether. You could download lodash locally and reference it via <script src="./node_modules/lodash"></script>.
So why bundle multiple files into fewer ones?
Performance. Sending one HTTP request for a bundled module is faster than sending multiple requests (HTTP requests have overhead: TCP handshakes, TLS connections, etc.). Even with HTTP/2 allowing parallel requests, there's a 25-request limit. If you have more than 25 modules, you need to combine them to stay within this limit.
The community even held a talk titled How Your Bundle Size Affects The Climate. It pointed out that while ancient websites were static and needed little JavaScript, modern websites are dynamic applications requiring significantly more code.
More JavaScript transmission means larger carbon footprints and longer browser processing times—additional energy consumption affecting our planet. Imagine a web app with tens of millions of monthly visitors. If bundling reduces JavaScript transmission per visit, users get faster experiences while reducing environmental impact.