C.W.K.
Stream
Lesson 01 of 07 · published

vite build — Inspect the Output

~11 min · vite-build, rollup, bundling

Level 0React Novice
0 XP0/54 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
Open the dist/ directory after a build. Every file in there is something you'll serve. If you can name what each one is and why it exists, you understand what shipped.

The output shape

After npm run build:

dist/
  index.html                   # the HTML shell with hashed asset links
  assets/
    index-[hash].js            # the main JS bundle
    index-[hash].css           # extracted CSS
    [Page]-[hash].js           # one chunk per React.lazy import
    [asset]-[hash].png         # static assets, fingerprinted

The hashes are content-derived. If the file content doesn't change, the hash doesn't change, and browsers/CDNs cache it forever (immutable). When the content changes, the hash changes, and the cache invalidates automatically.

What gets bundled

  • Your source — every TS/TSX/CSS/JSON file you imported (transitively).
  • Your dependencies — only what you actually import. Tree-shaking removes unused exports.
  • Static assets — images, fonts, SVGs imported via import logo from './logo.png'. The import returns a hashed URL.

What doesn't get bundled: anything in public/ (copied as-is, no hashing), env vars without the VITE_ prefix (server-only or kept out of the client entirely).

Inspecting the bundle

Install rollup-plugin-visualizer (a Vite plugin via Rollup). It generates a treemap of your bundle so you can see which packages are biggest. Common findings: a stray import of a huge library you only needed for one helper, an icon set imported as a whole instead of cherry-picked.

Ship what you understand. Run npm run build and look at dist/. Open the JS file in a text editor (it's minified but readable enough). The bundle is your product surface. Knowing what's in it is what separates 'I built something' from 'I shipped something.'

Code

Adding bundle visualizer·ts
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
import { visualizer } from "rollup-plugin-visualizer";

export default defineConfig({
  plugins: [
    react(),
    tailwindcss(),
    visualizer({
      filename: "dist/stats.html",
      open: true, // opens after build
      template: "treemap", // or 'sunburst', 'network'
    }),
  ],
});

// After `npm run build`: dist/stats.html opens with a visual treemap.
// Hover any rectangle to see size, gzip size, and module path.
What `npm run preview` does·bash
# Production-mode dev server — serves dist/ as a real static host would.
npm run build
npm run preview
# → http://localhost:4173 serves the production bundle.
# Use this to profile real perf (DevTools, Lighthouse) — not dev server.

External links

Exercise

Run npm run build in your bootstrap project. Open dist/. Identify: the HTML shell, the main JS chunk, any code-split chunks (you'll have some once you use React.lazy in lesson 2), the CSS file, any static assets. Install rollup-plugin-visualizer, rebuild, open dist/stats.html, and find your biggest dependency. Decide if it's earning its size.
Hint
Common culprits: moment.js (use date-fns or native Intl), lodash (cherry-pick from lodash/fn instead of import _ from 'lodash'), an icon library imported as a whole. Each can be replaced or cherry-picked for big savings.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.