Build Tools & Vite

Advanced · 17 min read · ▶ live playground · ✦ checkpoint

Your browser can run JavaScript modules, but a real app is more than a few .js files. A build tool is the workshop machine that serves your source code while you work and prepares a smaller, deployable version when you're ready to ship.

Why a build step exists

A build is the process that turns your source files into output files for the browser. Think of it like packing a project for travel: your working desk can have many folders, notes, and loose parts, but the suitcase needs the right things folded into the right places.

Four jobs show up again and again:

  • Bundling gathers the module graph into optimized output files, so the browser does not need to chase hundreds of separate source files in production.
  • Minification removes unnecessary bytes, like whitespace and long internal names, so files download faster.
  • Transpiling rewrites code from one JavaScript or syntax shape into another, usually so tools can support JSX, TypeScript, or selected browser targets.
  • Assets are non-JavaScript files your app ships, such as CSS, images, fonts, SVGs, and imported JSON.

Your source tree can stay human-shaped:

receipt-board/
  index.html
  package.json
  src/
    main.js
    receipt-view.js
    style.css
    logo.svg

The browser output can be machine-shaped:

dist/
  index.html
  assets/
    index-C8n2lPq1.js
    index-B4xq9Kc2.css
    logo-Df31a0.svg

You edit src/main.js. Users download dist/assets/index-C8n2lPq1.js. That filename can look strange because build tools often add a content hash, a short fingerprint made from the file's contents, so browsers cache files aggressively but still fetch the new file when the content changes.

Vite during development

Vite is a frontend build tool with two everyday faces: a development server for local work and a build command for production output.

A new Vite app usually starts from an npm create command:

npm create vite@latest receipt-board -- --template vanilla
cd receipt-board
npm install
npm run dev
 
# VITE ready
# Local: http://localhost:5173/

That transcript is the shape, not a command this lesson runs for you. In the project, package.json gives the workflow names:

{
  "name": "receipt-board",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  }
}

A development server is a local web server built for editing speed. Vite does not begin by bundling your whole app before the first page load. It serves source files over native ES modules and transforms files when the browser asks for them.

That matters because your index.html is part of the app graph:

<div id="app"></div>
<script type="module" src="/src/main.js"></script>

And src/main.js can import JavaScript and CSS directly:

import { renderReceiptList } from "./receipt-view.js";
import "./style.css";
 
const receipts = [
  { store: "Market Lane", totalCents: 1845 },
  { store: "Book Loft", totalCents: 3299 },
];
 
renderReceiptList(document.querySelector("#app"), receipts);

The plain browser needs type="module" to load ES modules. Vite's dev server makes the rest of the project feel direct: bare package imports, CSS imports, asset URLs, and transformed syntax can all pass through the tool before the browser sees them.

HMR keeps the page alive

Hot Module Replacement (HMR) means the dev server sends just the changed module to the browser after you save, instead of forcing a full page reload. It is like changing one card on the table while the rest of the table stays set.

When HMR works well, editing CSS updates the screen without losing form input. Editing a component in a framework can update the component without dropping the whole app state. Plain JavaScript modules may still reload more often than framework components, but the goal is the same: shorter feedback loops.

The important beginner point is not the hidden protocol. It is the habit: keep npm run dev running while you work, save a file, glance at the browser, repeat.

Production builds

Development speed and production output have different goals. The dev server optimizes for instant feedback. A production build optimizes for files you can deploy.

npm run build
 
# vite build
# dist/index.html
# dist/assets/index-C8n2lPq1.js
# dist/assets/index-B4xq9Kc2.css

Then you can test the built files locally:

npm run preview
 
# Local: http://localhost:4173/

preview is not the editing server. It serves the dist output so you can catch "works in dev, broken after build" problems before deployment.

In a small app, the build may feel unnecessary. In a real app, it becomes the point where packages, modules, CSS, images, environment choices, and browser targets become one deployable folder.

The wider tool zoo

You will hear names like esbuild, Rolldown, Rollup, Webpack, Parcel, and Rspack. They are all part of the JavaScript tooling world, but you do not need to collect them like badges.

esbuild is a very fast JavaScript bundler and transformer written in Go. It helped reset expectations for build-tool speed and still appears in ecosystem docs, old configs, and many tools.

Rolldown is the Rust-powered bundler inside modern Vite. Rust and Go are implementation details from your point of view. The useful beginner model is simpler: Vite is the tool you run, and tools like Rolldown are engines under the hood.

Choose the top-level tool that matches your project. For the next stretch of this course, that means Vite. If a future job uses another build tool, your core model transfers: dev server while you work, build command when you ship, output folder for deployment.

Build tools make your app runnable and shippable. Next, you add the guardrails that keep the code itself tidy: linters, formatters, and editor automation.

Checkpoint

Answer all three to mark this lesson complete

+50 XP on completion