DEV Community

Melissa Ashford for Lomray Software LLC

Posted on Fully Autonomous

We deleted Vite from our production server

vite-ssr-boost is an SSR framework built on Vite. Its production server used to start this way: load Vite, resolve vite.config, build the full CLI command tree, then serve the first request. None of that is needed to serve HTML.

In 8.4.x we cut it out. The numbers below are our own runs on a pinned template, M3 Pro, installed through npm.

What the production start used to do:

  • load Vite and evaluate vite.config
  • build the whole Commander command tree just to parse the flags of start
  • spin up the source analysis services that only dev mode uses

What it does now:

  • ssr-boost build writes a versioned build/server/ssr-boost.json with the resolved serving settings. Production reads that file and never evaluates the Vite config.
  • ssr-boost start parses its flags with Node's own parser. Every other command loads on demand, keyboard shortcuts load only when there is a TTY.
  • An import hook watches the serving path. It rejects vite, rolldown, rollup, commander, diff, parse5, semver, json5 and the babel packages, and it also rejects our own dev-only code: the cli commands, the build, manifest and route parsing services, the plugins. That is the part that keeps it honest. The hook catches accidental imports before they reach production.

What it bought:

  • cold start 354 ms to 249 ms. A plain Express server with renderToPipeableStream is 171 ms on the same machine.
  • RSS 142 MiB to 100 MiB. Same plain Express baseline: 69 MiB.

Then the per-request path. React's native Web stream on React 19.2+, the production shell cached instead of rebuilt, boundary scanning only while data frames can still arrive, a plain state script for routes without router data, static dispatch by built prefixes so there is no filesystem lookup per HTML request, the header queued at shell readiness, compression flushed before drain.

One more part, the one I would copy even if you skip everything else. Acceptance measures a plain Express baseline in the same run and fails the build if cold start goes past 2x that baseline. RSS has its own ceiling in the same file. So if a later change drags the start path back toward Vite, CI fails on a number instead of on someone's memory.

We also keep a public benchmark repo that runs five SSR frameworks weekly in CI and stores the raw json for every cell: https://github.com/Lomray-Software/ssr-benchmarks. Read it yourself, our claims here are about our own before and after, not about anyone else's framework.

If you run SSR on Vite, go look at what your production process loads before it answers anything. Count the modules, or run start under --cpu-prof.

We were loading a build tool in production. It cost about 100 ms and 40 MiB per process.

Code: https://github.com/Lomray-Software/vite-ssr-boost
Docs: https://lomray-software.github.io/vite-ssr-boost/
The PRs with the full detail: https://github.com/Lomray-Software/vite-ssr-boost/pull/53, https://github.com/Lomray-Software/vite-ssr-boost/pull/54, https://github.com/Lomray-Software/vite-ssr-boost/pull/55

Top comments (0)