ToolPopToolPop
JavaScript · Lesson 8 of 18

Modules, bundlers, and how code reaches the user

11 min readUpdated 24 Jun 2026

You have written functions, used arrays, called APIs, touched the DOM. The last question: how does all this code get from your laptop to a user in Pune opening your site on a slow 4G connection?

The answer is: modules, a bundler, and a host. Three small ideas, one lesson.

Diagram
rendering diagram...
From your editor to a user's browser, in five steps

ESM, the module system

Modern JavaScript splits code across files using import and export. This is called ESM (ES Modules) and it is the standard everywhere now.

js
// cart.js
export function addToCart(item) { /* ... */ }
export const TAX_RATE = 0.18;
 
// app.js
import { addToCart, TAX_RATE } from './cart.js';
  • Named exports are the common case. You can have many per file.
  • Default export is one per file: export default function App() {}, imported as import App from './app.js'.
  • Re-exports let one file gather and forward others: export * from './utils.js';.

Old Node code uses require and module.exports. That is CommonJS. Still works, but for anything new write ESM.

What a bundler does

You have 200 small files. The browser cannot fetch 200 files one by one without crawling. A bundler reads your entry point, walks every import, and produces a small number of optimized files.

  • Resolves dependencies. Figures out what imports what.
  • Combines files. One or a few JS chunks instead of hundreds.
  • Transforms code. TypeScript to JS, JSX to function calls, modern syntax to older if needed.
  • Optimizes assets. Inlines small images, hashes filenames for caching.

In 2026 the popular bundlers are Vite (dev), esbuild and Rollup (build), plus Next.js for full apps. You barely configure them. They just work.

Tree-shaking, the free optimization

If you import one function from a 500KB library and never use the rest, the bundler can drop the dead code from the final file. This is tree-shaking.

js
import { formatCurrency } from 'big-utils';
// the other 99 helpers in big-utils never make it to the bundle

It only works on ESM-style imports with static names. Dynamic imports and CommonJS often defeat it. This is one more reason to prefer ESM.

Minification

After bundling, the code is run through a minifier (esbuild, terser, swc). Whitespace gone, variable names shortened to one letter, comments stripped. A 200KB file becomes 60KB. Same behaviour, much smaller download.

You never write minified code yourself. The bundler does it on npm run build.

The file your user downloads looks nothing like the file you wrote. That is the point.

Shipping to production

"Ship to production" means three things:

  • Build. Run npm run build. Get a dist/ or out/ folder with the final HTML, JS, CSS.
  • Upload. Push those files to a host. Cloudflare Pages, Vercel, Netlify, S3, your own server.
  • Point a domain. Configure DNS so yoursite.com serves those files.

Most modern hosts collapse all three into a git push. You commit, they build and deploy automatically. The deploy URL is live in under a minute.

You did it

Eight lessons. Variables, functions, arrays, async, fetch, DOM, modules. That is the working vocabulary of a modern JavaScript developer.

Next track: pick React if you want to build apps, or Node if you want to build APIs. Either way, the language under your fingers is the same one you just learned. Go build something. A Swiggy menu clone is a great first project.

Free tools you can use while you learn

Chai0/1 done

Watching quietly. Tap me if you want a tip.

JS Playground
console
// hit run to see output

Try this (0 of 1 done)

  1. 1

    Build a small util object with `add` and `mul`. Log add(3,4) and mul(3,4).

    show answer
    const math = {
      add: (a, b) => a + b,
      mul: (a, b) => a * b,
    };
    console.log(math.add(3, 4));
    console.log(math.mul(3, 4));