Bundlers and Vite
Once a project grows past a single file, you need a way to combine all your modules, styles, and assets into something a browser can load efficiently. That is the job of a bundler. A bundler takes your source files, resolves the dependencies between them, and produces optimized output for production.
Why We Need Bundlers
Browsers support ES modules natively, so you might ask why we do not just ship the source files as they are. The problem is that a real app has dozens or hundreds of modules, and each import can trigger another HTTP request. HTTP/2 and HTTP/3 help, but a large module graph still adds overhead.
Bundlers solve several problems:
- Module resolution: they combine many files into fewer bundles, reducing network requests
- Performance: they minify code and remove unused exports to shrink file sizes
- Transformation: they convert TypeScript, JSX, and modern syntax into browser-compatible code
- Optimization: they apply techniques like tree shaking and code splitting automatically
Getting Started with Vite
Vite (French for “fast”) is a modern build tool that uses native ES modules during development and a Rollup-compatible production pipeline (Rollup today, with Rolldown rolling out in newer releases). It is fast, easy to configure, and supports TypeScript, JSX, and CSS out of the box.
To scaffold a new project:
npm create vite@latest my-app
cd my-app
npm install
npm run dev
This gives you a dev server with Hot Module Replacement (HMR), meaning your changes appear instantly in the browser without a full page reload.
Understanding Vite’s Project Structure
After scaffolding, your project looks like this:
my-app/
├── index.html
├── package.json
├── vite.config.js
├── src/
│ ├── main.js
│ └── style.css
└── public/
└── favicon.ico
Notice that index.html lives at the project root, not inside a public/ or dist/ folder. Vite treats it as the entry point and injects your scripts automatically.
Configuring Vite
Most projects need little or no configuration. But when you do need to customize things, Vite uses a vite.config.js file:
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
root: "./",
base: "/",
build: {
outDir: "dist",
minify: true, // use Vite's default minifier for your installed version
sourcemap: true,
},
server: {
port: 3000,
open: true, // opens browser automatically
},
});
The defineConfig helper gives you autocompletion in your editor, which helps you get the option names right.
Running Vite Commands
Vite projects come with three scripts in package.json:
npm run dev # Start dev server with hot reload
npm run build # Build optimized output for production
npm run preview # Preview the production build locally
My advice is to always run npm run preview after building to verify that your production bundle works correctly before deploying.
Why Vite Over Other Tools
Vite has become the default choice for new projects, for several reasons:
- Fast dev server — it serves source files as native ES modules and avoids full-app rebundles during development. Startup is usually near-instant.
- Hot Module Replacement — changes show up in the browser within milliseconds.
- Built-in support — TypeScript, JSX, CSS modules, and JSON imports all work without additional configuration.
- Optimized production builds — it produces efficient, tree-shaken, code-split bundles out of the box.