Astro, Nuxt, and SvelteKit handle Node.js HTTP requests natively. React
Router, SolidStart, and TanStack Start use Web APIs internally, so
benchmarks include the cost of their Node.js adapter layers (@react-router/node, h3, and srvx respectively)
Next.js defaults to React Server Components (RSC), a different rendering
model than traditional SSR. To keep the comparison fair, Next.js uses "use client" to opt out of RSC and use traditional SSR + hydration like most of the other
frameworks
Each framework renders a table of 1000 rows with two UUID columns
Measured using Lighthouse flow with Chromium via Puppeteer for accurate
browser metrics
First Paint and First Contentful Paint are measured on initial navigation
Interaction to Next Paint is measured by clicking the first row's detail
link
Benchmarks run 5 times and results are averaged
Next.js, TanStack Start, and React Router default to SSR with no per-route
opt-out. Next.js wraps the SPA table in a dynamic import with ssr: false to prevent build-time prerendering. TanStack Start uses its built-in spa mode.
React Router disables SSR entirely via ssr: false in its config.
All other frameworks (Nuxt, SvelteKit, SolidStart, Astro) disable SSR per-route
without a separate build.
Each framework renders a table of 1000 rows with two UUID columns
Measured using Lighthouse flow with Chromium via Puppeteer for accurate
browser metrics
First Paint and First Contentful Paint are measured on initial navigation
Interaction to Next Paint is measured by clicking the first row's detail
link
Benchmarks run 5 times and results are averaged
Next.js, TanStack Start, and React Router default to SSR with no per-route
opt-out. Next.js wraps the SPA table in a dynamic import with ssr: false to prevent build-time prerendering. TanStack Start uses its built-in spa mode.
React Router disables SSR entirely via ssr: false in its config.
All other frameworks (Nuxt, SvelteKit, SolidStart, Astro) disable SSR per-route
without a separate build.