Vite And Project Setup

Vite turns a pile of disconnected files into a fast dev server and an optimized production bundle -- and understanding what it is doing makes the config obvious.

May 15, 20264 min read2 / 2

The no-build-step setup from two posts ago has a hard ceiling. The moment you want to import from a second file, or pull in an npm package, or split code across modules, a CDN script tag breaks down. The browser cannot resolve those imports on its own.

That is the problem Vite solves.

What Vite Is

Vite is not primarily a bundler. The actual bundling is handled by Rollup underneath. What Vite provides is developer experience: a fast dev server with instant Hot Module Replacement, a simple config format, and an opinionated but sensible set of defaults that mean you rarely need to touch the configuration.

It was created by the same person who built Vue. The name is French for "fast." The dev server runs on port 5173, which is V-I-T-E in a combination of Roman numerals and leet speak -- a detail that is entirely useless but impossible to forget.

Git Ignore First

Before adding Vite, create a .gitignore so git does not track the things it should never track:

Plain text
node_modules dist .env coverage .DS_Store

node_modules is the big one. It can contain hundreds of thousands of files. Check it into git once and your repository is slow forever. The contract is: commit package.json, run npm install to restore node_modules. Everyone who clones the project gets the same packages without any of those files living in the repo.

Run git init if you want to start tracking the project -- even on a private repo, version control is worth having. If you are inside a larger cloned repo, git init creates an inner repo that git treats independently.

Installing Vite

Install Vite and its React plugin:

Bash
npm install --save-dev vite@5.4.2 @vitejs/plugin-react

Install React as a production dependency (not dev -- it ships to the browser):

Bash
npm install react@18.3.1 react-dom@18.3.1

Configuring Vite

Create vite.config.js at the project root:

JavaScript
import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; export default defineConfig({ plugins: [react()], });

That is the entire config. defineConfig is a helper that gives editor completions. The only thing Vite needs to know for a React project is that it should apply the React plugin, which handles JSX transformation. Everything else -- module resolution, HMR, dev server, source maps -- is on by default.

Updating the HTML

Remove the two CDN script tags from index.html. Replace them with a single module script pointing at your app entry:

HTML
<script type="module" src="./src/App.js"></script>

The type="module" attribute is required. Vite only works with ES modules -- the import/export style. If you leave it off, Vite will refuse to serve the file.

Updating the Scripts

Remove the CDN React references from App.js and add proper imports:

JavaScript
import React from "react"; import { createRoot } from "react-dom/client"; const App = () => { return React.createElement("div", {}, React.createElement("h1", {}, "Padre Gino's")); }; const container = document.getElementById("root"); const root = createRoot(container); root.render(React.createElement(App));

Notice react-dom/client -- not react-dom. The /client path is the modern entry point. The top-level react-dom still works in React 18 but will likely break in React 19. Use /client and you are forward-compatible.

Add scripts to package.json, plus "type": "module" so tools know this project uses ES modules:

JSON
{ "type": "module", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview", "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css}\"", "lint": "eslint" } }

Vite pipeline: source files and npm packages go in, dev server or production bundle comes out ExpandVite pipeline: source files and npm packages go in, dev server or production bundle comes out

Three Commands, Three Purposes

npm run dev starts the local dev server. This is the command you run every time you sit down to work. Changes to source files appear in the browser instantly without a full page reload -- that is HMR.

npm run build produces an optimized static bundle in dist/. This is what a CI pipeline runs before deploying to Vercel, Netlify, or any static host. Vite minifies the output, chunks it for caching, and generates source maps.

npm run preview serves the dist/ folder locally, as if it were a production environment. Most developers rarely need this, but it is the right tool when a bug only reproduces in the production build and not in the dev server.

Now run npm run dev and open localhost:5173. The app looks exactly the same as it did with the CDN script tags. The difference is invisible from the browser -- but the project is now set up to scale.

In the next post JSX arrives and the React.createElement calls finally go away.

The Essentials

  1. Vite wraps Rollup with great developer experience. The bundling engine is Rollup. Vite adds HMR, simple config, and a fast dev server on top.
  2. type: "module" is required. Vite works exclusively with ES modules. Add it to package.json and <script type="module"> to the HTML entry point.
  3. react-dom/client, not react-dom. The /client path is the modern React 18+ entry point for browser rendering. Use it to stay compatible with React 19.
  4. Three script commands. dev for local work, build for CI/production, preview for debugging production-only issues.
  5. .gitignore before first commit. node_modules and dist should never be committed. node_modules is restored by npm install; dist is regenerated by npm run build.

Further Reading and Watching