Module Bundling Workflow
Module bundling is the process by which a build tool takes a graph of JavaScript module files (plus CSS, images, fonts, and other assets), resolves all their dependencies, transforms them, and outputs optimized files suitable for delivery to a browser.
Module bundling is the process by which a build tool takes a graph of JavaScript module files (plus CSS, images, fonts, and other assets), resolves all their dependencies, transforms them, and outputs optimized files suitable for delivery to a browser.
The bundler's work begins with one or more entry points — the top-level files that the application starts with (src/main.js, src/index.tsx). The bundler reads each entry point, parses it into an AST (Abstract Syntax Tree), and finds all import and require statements. It recursively follows each import to build a dependency graph — a directed acyclic graph where each node is a module file and each edge is an import relationship.
As the graph is built, each module is processed through a pipeline of loaders (webpack) or plugins (Vite/Rollup). TypeScript files are transpiled to JavaScript. JSX is transformed into React.createElement or equivalent calls. CSS modules are converted to scoped class names. Images below a size threshold are inlined as base64 data URIs. Babel transforms modern JavaScript syntax to a target compatibility level.
With the full graph loaded and transformed, the bundler performs tree shaking — dead code elimination based on static analysis of ES module import/export statements. Modules or exports that are imported but never used are excluded from the output. This is why switching from CommonJS (require) to ES modules is a prerequisite for effective tree shaking: CommonJS exports are dynamic and cannot be statically analyzed.
The remaining modules are concatenated into output chunks. A single-chunk build produces one large JS file; code splitting (see Code Splitting Architecture) produces multiple smaller chunks. Finally, the bundler minifies output (removing whitespace, shortening variable names) and optionally generates source maps for debugging. Hashed filenames are added for long-term caching. See Lazy Loading Components for how dynamic imports create async chunk boundaries in this graph.