localhost:5173 / dev-server-startup

What happens between npm run dev and the page on localhost:5173

Starting the Vite dev server takes five steps: npm resolves the vite binary, Vite reads the config, dependencies are pre-bundled, the server listens on 5173, and the browser opens an HMR WebSocket on the first request.

The five steps

Every symptom on this page belongs to exactly one of them. Finding the step is most of the work.

  • 1. npm resolves the vite binary from node_modules/.bin and runs it.
  • 2. Vite loads vite.config.js and merges it with CLI flags.
  • 3. The optimizer crawls your entry points and pre-bundles the dependencies it finds.
  • 4. The server binds to a port — 5173 unless it is taken or configured otherwise.
  • 5. The first request loads the app, and the client opens a WebSocket for HMR.

What the successful start looks like

Vite prints the address block once it is listening. Until that block appears, nothing is serving on 5173.

terminal
$ npm run dev

  VITE v8.1.5  ready in 412 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

Step 1 — npm resolves the binary

The dev script runs vite, and npm looks for it in node_modules/.bin. If the package was never installed, or the install was interrupted, the shell reports a missing command and nothing else happens. This is the failure that never reaches 5173 at all, and it is the most searched one.

Step 2 — the config is read

Vite loads vite.config.js from the project root unless -c points elsewhere. CLI flags win over the config file, which is why a --port on the command line beats server.port. A framework wrapper such as Nuxt or SvelteKit adds a third layer and may override both.

Step 3 — dependencies are pre-bundled

Vite crawls your source for bare imports and converts those packages to ESM once, writing the result to node_modules/.vite. On a cold start this is the slowest step. On later starts it is skipped, because the cache is keyed to the lockfile, the patches directory, the relevant config fields and NODE_ENV — change one of those and the step runs again.

Step 4 — the server binds to a port

Vite listens on 5173 by default and on localhost only. If 5173 is taken, it moves to the next free port and prints the one it actually got, which is why the terminal sometimes says 5174. If host is left at the default, the address answers on your machine and nowhere else.

Step 5 — the HMR socket opens

Once the page loads, the client opens a WebSocket back to the server. Edits travel over that socket. If it fails to connect, the page still renders, but nothing updates until you reload by hand — so a page that loads and never changes is a step-5 problem, not a step-3 one.

Which symptom belongs to which step

  • Command not found, or the script exits instantly — step 1.
  • Your port or proxy setting appears to be ignored — step 2.
  • Long cold start, or a reload right after the first load — step 3.
  • The terminal says 5174, or the address answers nowhere but on your machine — step 4.
  • The page loads once and never updates again — step 5.
  • The page loads and stays blank — none of them: the server answered, so the problem is in your application code.

# faq

Questions

Why does the first start take so much longer than the next one?

Because dependency pre-bundling only runs on a cold start. Later starts reuse node_modules/.vite until something the cache is keyed to changes.

Is vite dev different from npm run dev?

No. The dev script calls the same binary. vite, vite dev and vite serve all start the dev server.

The terminal shows a URL but the browser will not open it.

Then the server is listening and the problem is between the browser and the address — check whether the printed port really is 5173 and whether you typed https on a server serving http.

Does the dev server build my site?

No. It serves source files over native ESM and transforms them per request. The build is a separate command, and it is served on port 4173 by vite preview.

# next

Related

  • When npm run dev does not bring up localhost:5173Read the terminal before the browser: npm run dev fails at one of four points — a missing script, a missing binary, a config error, or a port that is not the one you are opening.
  • Dependency pre-bundling on the Vite dev serverVite converts your dependencies to ESM once before serving them on 5173 and caches the result in node_modules/.vite — optimizeDeps controls what goes into that step and what stays out of it.
  • Hot Module Replacement on localhost:5173HMR swaps a changed module in the running page over a WebSocket instead of reloading it; when that WebSocket cannot connect, Vite falls back to full page reloads or stops updating at all.
  • Clearing the Vite dependency cacheVite caches pre-bundled dependencies in node_modules/.vite — delete that directory or start with --force to rebuild it.
  • localhost:5173 loads but the page stays blankA blank page on localhost:5173 is a dev-server problem only if the document request itself fails — a 404 with an empty body means Vite found no index.html in the project root — while a 200 with an empty page means a script failed in the browser, which Vite does not show in the terminal by default.
  • vite: command not found / 'vite' is not recognizedThe shell cannot find the vite binary: either the vite package is not in node_modules of this project, or it is installed and you typed vite outside an npm script, where node_modules/.bin is not on the PATH.
  • Changing the port the Vite dev server usesSet server.port in vite.config.js, or pass --port on the command line; add strictPort: true if you want Vite to fail instead of silently moving to the next free port.
  • 504 (Outdated Optimize Dep) on localhost:5173The 504 means the page asked for a dependency pre-bundle that Vite had just replaced with a new one, so the dev server refuses the stale URL and expects the page reload it already announced.
  • localhost:5173 — the port itselfWhat the address means, common dev ports, and the autocomplete fix.

# sources

Checked against the Vite documentation on 2026-09-11.