Next.js
Dev Time Performance
Measured using pnpm on GitHub Actions (ubuntu-latest, Node 24) based on the starter project set up by each framework's CLI.
| Prod Deps | Dev Deps | Dup. Deps | node_modules | node_modules (prod) | Dep Install Size | Graph |
|---|---|---|---|---|---|---|
| 3 | 6 | 12 | 560.04MB | 436.00MB | 506.22MB | View |
| Metric | Avg | Min | Max |
|---|---|---|---|
| Install | 3.53s | 3.21s | 4.47s |
| Cold Build | 6.79s | 6.62s | 7.01s |
| Warm Build | 6.75s | 6.72s | 6.79s |
Build output size: 6.18MB
Unnecessary Core-JS Polyfills
302 core-js polyfill modules are bundled but already natively supported by the last 2 major versions of Chrome, Firefox, Safari, and Edge โ code users download even though their browser already supports it natively. The containing chunk is approximately 110.0 KB (chunk size, not isolated core-js bytes).
View 302 unnecessary modules by category
-
es.typed-array.*39 -
es.array.*37 -
es.string.*36 -
es.object.*28 -
es.math.*18 -
web.*17 -
es.symbol.*15 -
es.reflect.*14 -
es.number.*13 -
es.date.*8 -
esnext.array.*8 -
es.regexp.*7 -
esnext.set.*7 -
es.array-buffer.*6 -
esnext.typed-array.*6 -
es.promise.*5 -
es.set.*5 -
esnext.string.*4 -
es.function.*3 -
esnext.array-buffer.*3 -
esnext.promise.*3 -
es.error.*2 -
es.aggregate-error.*2 -
es.map.*2 -
esnext.object.*2 -
es.data-view.*1 -
es.escape.*1 -
es.global-this.*1 -
es.json.*1 -
es.parse-float.*1 -
es.parse-int.*1 -
es.unescape.*1 -
es.weak-map.*1 -
es.weak-set.*1 -
esnext.aggregate-error.*1 -
esnext.global-this.*1 -
esnext.map.*1
Duplicate Dependencies
12 duplicate dependencies detected across this starter's node_modules.
View 12 duplicate dependencies
- debug
- json5
- semver
- eslint-visitor-keys
- minimatch
- globals
- ignore
- postcss
- brace-expansion
- resolve
- glob-parent
- picomatch
Runtime Performance
SSR Performance
Measured on GitHub Actions (ubuntu-latest, Node 24) using custom SSR benchmark apps.
| Framework | Ops/sec | Avg Latency | Body Size | Duplication |
|---|---|---|---|---|
| Baseline HTML | 708 | 1.422ms | 96.81kb | 1x |
| Next.js | 138 | 7.371ms | 199.11kb | 2x |
Methodology
- Each framework renders a table of 1000 rows with two UUID columns
- Mock HTTP requests bypass TCP overhead for accurate rendering measurement
- Data is loaded asynchronously to simulate real-world data fetching
- Duplication factor indicates how many times each UUID appears in the response (1x = optimal, 2x = includes hydration payload)
- Benchmarks run for 10 seconds using tinybench
-
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 - Inspired by eknkc/ssr-benchmark
SPA Performance
Measured on GitHub Actions (ubuntu-latest, Node 24) using Lighthouse flow with Chromium.
| Framework | First Paint | FCP | INP |
|---|---|---|---|
| Next.js | 380.8ms | 380.98ms | 20.58ms |
Methodology
- 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
dynamicimport withssr: falseto prevent build-time prerendering. TanStack Start uses its built-in spa mode. React Router disables SSR entirely viassr: falsein its config. All other frameworks (Nuxt, SvelteKit, SolidStart, Astro) disable SSR per-route without a separate build.
MPA Performance
Measured on GitHub Actions (ubuntu-latest, Node 24) using Lighthouse flow with Chromium.
| Framework | First Paint | FCP | INP |
|---|---|---|---|
| Next.js | 190ms | 189.73ms | 17.51ms |
Methodology
- 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
dynamicimport withssr: falseto prevent build-time prerendering. TanStack Start uses its built-in spa mode. React Router disables SSR entirely viassr: falsein its config. All other frameworks (Nuxt, SvelteKit, SolidStart, Astro) disable SSR per-route without a separate build.