From e25dbb0e3854ad88c829a965b4754c02a806e096 Mon Sep 17 00:00:00 2001 From: Alexander Karan Date: Mon, 22 Jun 2026 20:15:57 +0800 Subject: [PATCH] Changed Name --- .github/frameworks.json | 32 ++--- .github/workflows/generate-stats.yml | 18 +-- .github/workflows/measure-framework.yml | 54 +++---- .github/workflows/preview-stats.yml | 8 +- .github/workflows/validate-stats.yml | 24 ++-- CONTRIBUTING.md | 2 +- Dockerfile | 2 +- Roadmap.md | 2 +- packages/app-astro/ci-stats.json | 24 ++-- .../components/ClientSideRenderedDetail.tsx | 3 + ...SpaPage.tsx => ClientSideRenderedPage.tsx} | 4 +- .../app-astro/src/components/SpaDetail.tsx | 3 - .../{spa.astro => client-side-rendered.astro} | 6 +- .../src/pages/client-side-rendered/[id].astro | 16 +++ .../{mpa.astro => server-side-rendered.astro} | 4 +- .../{mpa => server-side-rendered}/[id].astro | 2 +- packages/app-astro/src/pages/spa/[id].astro | 16 --- packages/app-astro/stats/5.16.15.json | 24 ++-- packages/app-baseline-html/ci-stats.json | 14 +- packages/app-mastro/ci-stats.json | 14 +- .../ClientSideRenderedTable.tsx} | 4 +- .../[id]/page.tsx | 2 +- .../app/client-side-rendered/page.tsx | 12 ++ .../[id]/page.tsx | 2 +- .../{mpa => server-side-rendered}/page.tsx | 4 +- packages/app-next-js/app/spa/page.tsx | 9 -- packages/app-next-js/ci-stats.json | 24 ++-- packages/app-next-js/stats/16.1.1.json | 24 ++-- .../{spa => client-side-rendered}/[id].vue | 0 .../{spa => client-side-rendered}/index.vue | 2 +- .../{mpa => server-side-rendered}/[id].vue | 0 .../{mpa => server-side-rendered}/index.vue | 2 +- packages/app-nuxt/ci-stats.json | 24 ++-- packages/app-nuxt/stats/4.2.2.json | 24 ++-- packages/app-react-router/app/routes.ts | 17 ++- ...il.tsx => client-side-rendered.detail.tsx} | 2 +- .../{spa.tsx => client-side-rendered.tsx} | 4 +- .../app/routes/mpa.detail.tsx | 10 -- .../routes/server-side-rendered.detail.tsx | 12 ++ .../{mpa.tsx => server-side-rendered.tsx} | 8 +- packages/app-react-router/ci-stats.json | 24 ++-- packages/app-react-router/stats/7.10.1.json | 24 ++-- packages/app-solid-start/ci-stats.json | 24 ++-- .../{spa => client-side-rendered}/[id].tsx | 2 +- .../{spa => client-side-rendered}/index.tsx | 4 +- .../{mpa => server-side-rendered}/[id].tsx | 2 +- .../{mpa => server-side-rendered}/index.tsx | 6 +- packages/app-solid-start/stats/1.2.1.json | 24 ++-- packages/app-sveltekit/ci-stats.json | 24 ++-- .../+page.svelte | 2 +- .../{spa => client-side-rendered}/+page.ts | 0 .../[id]/+page.svelte | 0 .../[id]/+page.ts | 0 .../+page.server.ts | 0 .../+page.svelte | 2 +- .../{mpa => server-side-rendered}/+page.ts | 0 .../[id]/+page.server.ts | 0 .../[id]/+page.svelte | 0 .../[id]/+page.ts | 0 packages/app-sveltekit/stats/2.49.4.json | 24 ++-- .../app-tanstack-start-react/ci-stats.json | 24 ++-- .../src/routeTree.gen.ts | 134 ++++++++++-------- .../{spa.tsx => client-side-rendered.tsx} | 8 +- .../src/routes/client-side-rendered_.$id.tsx | 11 ++ .../src/routes/mpa_.$id.tsx | 11 -- .../{mpa.tsx => server-side-rendered.tsx} | 8 +- .../src/routes/server-side-rendered_.$id.tsx | 11 ++ .../src/routes/spa_.$id.tsx | 11 -- .../stats/1.145.3.json | 24 ++-- .../app-tanstack-start-react/vite.config.ts | 6 +- ...entSideRenderedStatsMethodologyNotes.astro | 11 +- packages/docs/src/components/MPACharts.astro | 18 --- .../src/components/SSRBodySizeChart.astro | 16 --- packages/docs/src/components/SSRCharts.astro | 18 --- .../docs/src/components/SSROpsChart.astro | 16 --- .../SSRRequestThroughputBodySizeChart.astro | 20 +++ .../SSRRequestThroughputCharts.astro | 18 +++ ...=> SSRRequestThroughputLatencyChart.astro} | 6 +- .../SSRRequestThroughputOpsChart.astro | 20 +++ ...uestThroughputStatsMethodologyNotes.astro} | 7 +- .../SSRRequestThroughputStatsTable.astro | 37 +++++ .../docs/src/components/SSRStatsTable.astro | 37 ----- .../components/ServerSideRenderedCharts.astro | 18 +++ ...astro => ServerSideRenderedFCPChart.astro} | 4 +- ....astro => ServerSideRenderedFPChart.astro} | 4 +- ...astro => ServerSideRenderedINPChart.astro} | 4 +- ...erSideRenderedStatsMethodologyNotes.astro} | 9 +- ...tro => ServerSideRenderedStatsTable.astro} | 12 +- packages/docs/src/content.config.ts | 28 ++-- .../docs/src/content/runtime/app-astro.json | 26 ++-- .../content/runtime/app-baseline-html.json | 18 +-- .../docs/src/content/runtime/app-mastro.json | 18 +-- .../docs/src/content/runtime/app-next-js.json | 26 ++-- .../docs/src/content/runtime/app-nuxt.json | 26 ++-- .../src/content/runtime/app-react-router.json | 26 ++-- .../src/content/runtime/app-solid-start.json | 26 ++-- .../src/content/runtime/app-sveltekit.json | 26 ++-- .../runtime/app-tanstack-start-react.json | 26 ++-- packages/docs/src/lib/collections.ts | 62 +++++--- .../docs/src/pages/framework/[slug].astro | 70 ++++----- packages/docs/src/pages/index.astro | 22 +-- packages/docs/src/pages/run-time.astro | 26 ++-- packages/stats-generator/package.json | 6 +- .../src/clientSideRendered/index.ts | 64 +++++---- .../src/clientSideRendered/run-benchmark.ts | 19 +-- .../src/clientSideRendered/types.ts | 6 +- packages/stats-generator/src/collect-stats.ts | 2 +- packages/stats-generator/src/mpa/types.ts | 25 ---- ... => run-client-side-rendered-benchmark.ts} | 25 ++-- ... => run-server-side-rendered-benchmark.ts} | 38 +++-- ...> run-ssr-request-throughput-benchmark.ts} | 43 ++++-- packages/stats-generator/src/save-ci-stats.ts | 92 +++++++----- packages/stats-generator/src/schemas.ts | 20 +-- ...-spa.ts => static-client-side-rendered.ts} | 0 .../src/serve/tanstack-start.ts | 8 +- .../src/{mpa => serverSideRendered}/index.ts | 62 ++++---- .../run-benchmark.ts | 29 ++-- .../src/serverSideRendered/types.ts | 29 ++++ packages/stats-generator/src/ssr/index.ts | 113 --------------- packages/stats-generator/src/ssr/types.ts | 36 ----- .../handlers/astro.ts | 4 +- .../handlers/baseline-html.ts | 9 +- .../handlers/mastro.ts | 4 +- .../handlers/nextjs.ts | 6 +- .../handlers/nuxt.ts | 4 +- .../handlers/react-router.ts | 4 +- .../handlers/solid-start.ts | 4 +- .../handlers/sveltekit.ts | 4 +- .../handlers/tanstack-start.ts | 4 +- .../src/ssrRequestThroughput/index.ts | 124 ++++++++++++++++ .../mock-http.ts | 0 .../run-benchmark.ts | 26 ++-- .../src/ssrRequestThroughput/types.ts | 38 +++++ packages/stats-generator/src/types.ts | 32 +++-- packages/stats-generator/src/utils.ts | 63 ++++++++ .../stats-generator/src/validate-stats.ts | 10 +- 136 files changed, 1424 insertions(+), 1098 deletions(-) create mode 100644 packages/app-astro/src/components/ClientSideRenderedDetail.tsx rename packages/app-astro/src/components/{SpaPage.tsx => ClientSideRenderedPage.tsx} (81%) delete mode 100644 packages/app-astro/src/components/SpaDetail.tsx rename packages/app-astro/src/pages/{spa.astro => client-side-rendered.astro} (55%) create mode 100644 packages/app-astro/src/pages/client-side-rendered/[id].astro rename packages/app-astro/src/pages/{mpa.astro => server-side-rendered.astro} (79%) rename packages/app-astro/src/pages/{mpa => server-side-rendered}/[id].astro (80%) delete mode 100644 packages/app-astro/src/pages/spa/[id].astro rename packages/app-next-js/app/{spa/SpaTable.tsx => client-side-rendered/ClientSideRenderedTable.tsx} (81%) rename packages/app-next-js/app/{spa => client-side-rendered}/[id]/page.tsx (72%) create mode 100644 packages/app-next-js/app/client-side-rendered/page.tsx rename packages/app-next-js/app/{mpa => server-side-rendered}/[id]/page.tsx (60%) rename packages/app-next-js/app/{mpa => server-side-rendered}/page.tsx (75%) delete mode 100644 packages/app-next-js/app/spa/page.tsx rename packages/app-nuxt/app/pages/{spa => client-side-rendered}/[id].vue (100%) rename packages/app-nuxt/app/pages/{spa => client-side-rendered}/index.vue (84%) rename packages/app-nuxt/app/pages/{mpa => server-side-rendered}/[id].vue (100%) rename packages/app-nuxt/app/pages/{mpa => server-side-rendered}/index.vue (82%) rename packages/app-react-router/app/routes/{spa.detail.tsx => client-side-rendered.detail.tsx} (65%) rename packages/app-react-router/app/routes/{spa.tsx => client-side-rendered.tsx} (81%) delete mode 100644 packages/app-react-router/app/routes/mpa.detail.tsx create mode 100644 packages/app-react-router/app/routes/server-side-rendered.detail.tsx rename packages/app-react-router/app/routes/{mpa.tsx => server-side-rendered.tsx} (66%) rename packages/app-solid-start/src/routes/{spa => client-side-rendered}/[id].tsx (71%) rename packages/app-solid-start/src/routes/{spa => client-side-rendered}/index.tsx (81%) rename packages/app-solid-start/src/routes/{mpa => server-side-rendered}/[id].tsx (67%) rename packages/app-solid-start/src/routes/{mpa => server-side-rendered}/index.tsx (79%) rename packages/app-sveltekit/src/routes/{spa => client-side-rendered}/+page.svelte (83%) rename packages/app-sveltekit/src/routes/{spa => client-side-rendered}/+page.ts (100%) rename packages/app-sveltekit/src/routes/{spa => client-side-rendered}/[id]/+page.svelte (100%) rename packages/app-sveltekit/src/routes/{spa => client-side-rendered}/[id]/+page.ts (100%) rename packages/app-sveltekit/src/routes/{mpa => server-side-rendered}/+page.server.ts (100%) rename packages/app-sveltekit/src/routes/{mpa => server-side-rendered}/+page.svelte (79%) rename packages/app-sveltekit/src/routes/{mpa => server-side-rendered}/+page.ts (100%) rename packages/app-sveltekit/src/routes/{mpa => server-side-rendered}/[id]/+page.server.ts (100%) rename packages/app-sveltekit/src/routes/{mpa => server-side-rendered}/[id]/+page.svelte (100%) rename packages/app-sveltekit/src/routes/{mpa => server-side-rendered}/[id]/+page.ts (100%) rename packages/app-tanstack-start-react/src/routes/{spa.tsx => client-side-rendered.tsx} (75%) create mode 100644 packages/app-tanstack-start-react/src/routes/client-side-rendered_.$id.tsx delete mode 100644 packages/app-tanstack-start-react/src/routes/mpa_.$id.tsx rename packages/app-tanstack-start-react/src/routes/{mpa.tsx => server-side-rendered.tsx} (70%) create mode 100644 packages/app-tanstack-start-react/src/routes/server-side-rendered_.$id.tsx delete mode 100644 packages/app-tanstack-start-react/src/routes/spa_.$id.tsx delete mode 100644 packages/docs/src/components/MPACharts.astro delete mode 100644 packages/docs/src/components/SSRBodySizeChart.astro delete mode 100644 packages/docs/src/components/SSRCharts.astro delete mode 100644 packages/docs/src/components/SSROpsChart.astro create mode 100644 packages/docs/src/components/SSRRequestThroughputBodySizeChart.astro create mode 100644 packages/docs/src/components/SSRRequestThroughputCharts.astro rename packages/docs/src/components/{SSRLatencyChart.astro => SSRRequestThroughputLatencyChart.astro} (70%) create mode 100644 packages/docs/src/components/SSRRequestThroughputOpsChart.astro rename packages/docs/src/components/{SSRStatsMethodologyNotes.astro => SSRRequestThroughputStatsMethodologyNotes.astro} (84%) create mode 100644 packages/docs/src/components/SSRRequestThroughputStatsTable.astro delete mode 100644 packages/docs/src/components/SSRStatsTable.astro create mode 100644 packages/docs/src/components/ServerSideRenderedCharts.astro rename packages/docs/src/components/{MPAFCPChart.astro => ServerSideRenderedFCPChart.astro} (67%) rename packages/docs/src/components/{MPAFPChart.astro => ServerSideRenderedFPChart.astro} (67%) rename packages/docs/src/components/{MPAINPChart.astro => ServerSideRenderedINPChart.astro} (67%) rename packages/docs/src/components/{MPAStatsMethodologyNotes.astro => ServerSideRenderedStatsMethodologyNotes.astro} (54%) rename packages/docs/src/components/{MPAStatsTable.astro => ServerSideRenderedStatsTable.astro} (59%) delete mode 100644 packages/stats-generator/src/mpa/types.ts rename packages/stats-generator/src/{run-spa-benchmark.ts => run-client-side-rendered-benchmark.ts} (74%) rename packages/stats-generator/src/{run-mpa-benchmark.ts => run-server-side-rendered-benchmark.ts} (62%) rename packages/stats-generator/src/{run-ssr-benchmark.ts => run-ssr-request-throughput-benchmark.ts} (55%) rename packages/stats-generator/src/serve/{static-spa.ts => static-client-side-rendered.ts} (100%) rename packages/stats-generator/src/{mpa => serverSideRendered}/index.ts (61%) rename packages/stats-generator/src/{mpa => serverSideRendered}/run-benchmark.ts (84%) create mode 100644 packages/stats-generator/src/serverSideRendered/types.ts delete mode 100644 packages/stats-generator/src/ssr/index.ts delete mode 100644 packages/stats-generator/src/ssr/types.ts rename packages/stats-generator/src/{ssr => ssrRequestThroughput}/handlers/astro.ts (73%) rename packages/stats-generator/src/{ssr => ssrRequestThroughput}/handlers/baseline-html.ts (66%) rename packages/stats-generator/src/{ssr => ssrRequestThroughput}/handlers/mastro.ts (71%) rename packages/stats-generator/src/{ssr => ssrRequestThroughput}/handlers/nextjs.ts (79%) rename packages/stats-generator/src/{ssr => ssrRequestThroughput}/handlers/nuxt.ts (73%) rename packages/stats-generator/src/{ssr => ssrRequestThroughput}/handlers/react-router.ts (81%) rename packages/stats-generator/src/{ssr => ssrRequestThroughput}/handlers/solid-start.ts (82%) rename packages/stats-generator/src/{ssr => ssrRequestThroughput}/handlers/sveltekit.ts (71%) rename packages/stats-generator/src/{ssr => ssrRequestThroughput}/handlers/tanstack-start.ts (82%) create mode 100644 packages/stats-generator/src/ssrRequestThroughput/index.ts rename packages/stats-generator/src/{ssr => ssrRequestThroughput}/mock-http.ts (100%) rename packages/stats-generator/src/{ssr => ssrRequestThroughput}/run-benchmark.ts (82%) create mode 100644 packages/stats-generator/src/ssrRequestThroughput/types.ts diff --git a/.github/frameworks.json b/.github/frameworks.json index 348d5411..f0e0b116 100644 --- a/.github/frameworks.json +++ b/.github/frameworks.json @@ -8,7 +8,7 @@ "package": "app-baseline-html", "buildScript": "build", "buildOutputDir": ".", - "measurements": [{ "type": "ssr" }] + "measurements": [{ "type": "ssrRequestThroughput" }] } }, { @@ -31,9 +31,9 @@ "buildScript": "build", "buildOutputDir": "dist", "measurements": [ - { "type": "ssr" }, + { "type": "ssrRequestThroughput" }, { "type": "clientSideRendered" }, - { "type": "mpa" } + { "type": "serverSideRendered" } ] } }, @@ -56,7 +56,7 @@ "package": "app-mastro", "buildScript": "build", "buildOutputDir": "generated", - "measurements": [{ "type": "ssr" }] + "measurements": [{ "type": "ssrRequestThroughput" }] } }, { @@ -79,9 +79,9 @@ "buildScript": "build", "buildOutputDir": ".next", "measurements": [ - { "type": "ssr" }, + { "type": "ssrRequestThroughput" }, { "type": "clientSideRendered" }, - { "type": "mpa" } + { "type": "serverSideRendered" } ] } }, @@ -105,9 +105,9 @@ "buildScript": "build", "buildOutputDir": ".output", "measurements": [ - { "type": "ssr" }, + { "type": "ssrRequestThroughput" }, { "type": "clientSideRendered" }, - { "type": "mpa" } + { "type": "serverSideRendered" } ] } }, @@ -131,9 +131,9 @@ "buildScript": "build", "buildOutputDir": "build", "measurements": [ - { "type": "ssr" }, + { "type": "ssrRequestThroughput" }, { "type": "clientSideRendered" }, - { "type": "mpa" } + { "type": "serverSideRendered" } ] } }, @@ -157,9 +157,9 @@ "buildScript": "build", "buildOutputDir": ".output", "measurements": [ - { "type": "ssr" }, + { "type": "ssrRequestThroughput" }, { "type": "clientSideRendered" }, - { "type": "mpa" } + { "type": "serverSideRendered" } ] } }, @@ -183,9 +183,9 @@ "buildScript": "build", "buildOutputDir": "build", "measurements": [ - { "type": "ssr" }, + { "type": "ssrRequestThroughput" }, { "type": "clientSideRendered" }, - { "type": "mpa" } + { "type": "serverSideRendered" } ] } }, @@ -209,9 +209,9 @@ "buildScript": "build", "buildOutputDir": ".output", "measurements": [ - { "type": "ssr" }, + { "type": "ssrRequestThroughput" }, { "type": "clientSideRendered" }, - { "type": "mpa" } + { "type": "serverSideRendered" } ] } } diff --git a/.github/workflows/generate-stats.yml b/.github/workflows/generate-stats.yml index 9bb4927d..21e92770 100644 --- a/.github/workflows/generate-stats.yml +++ b/.github/workflows/generate-stats.yml @@ -24,10 +24,10 @@ jobs: outputs: install-matrix: ${{ steps.set-matrix.outputs.install }} build-matrix: ${{ steps.set-matrix.outputs.build }} - ssr-matrix: ${{ steps.set-matrix.outputs.ssr }} + ssr-request-throughput-matrix: ${{ steps.set-matrix.outputs.ssr-request-throughput }} deps-matrix: ${{ steps.set-matrix.outputs.deps }} - spa-matrix: ${{ steps.set-matrix.outputs.spa }} - mpa-matrix: ${{ steps.set-matrix.outputs.mpa }} + client-side-rendered-matrix: ${{ steps.set-matrix.outputs.client-side-rendered }} + server-side-rendered-matrix: ${{ steps.set-matrix.outputs.server-side-rendered }} steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -38,10 +38,10 @@ jobs: FRAMEWORKS=$(cat .github/frameworks.json) echo "install=$(echo "$FRAMEWORKS" | jq -c '[.[] | select(.starter) | select(.starter.measurements | map(.type) | contains(["install"])) | {name, displayName, package: .starter.package, buildScript: .starter.buildScript, buildOutputDir: .starter.buildOutputDir, measurements: .starter.measurements}]')" >> $GITHUB_OUTPUT echo "build=$(echo "$FRAMEWORKS" | jq -c '[.[] | select(.starter) | select(.starter.measurements | map(.type) | contains(["build"])) | {name, displayName, package: .starter.package, buildScript: .starter.buildScript, buildOutputDir: .starter.buildOutputDir, measurements: .starter.measurements}]')" >> $GITHUB_OUTPUT - echo "ssr=$(echo "$FRAMEWORKS" | jq -c '[.[] | select(.app) | select(.app.measurements | map(.type) | contains(["ssr"])) | {name, displayName, package: .app.package, buildScript: .app.buildScript, buildOutputDir: .app.buildOutputDir, measurements: .app.measurements}]')" >> $GITHUB_OUTPUT + echo "ssr-request-throughput=$(echo "$FRAMEWORKS" | jq -c '[.[] | select(.app) | select(.app.measurements | map(.type) | contains(["ssrRequestThroughput"])) | {name, displayName, package: .app.package, buildScript: .app.buildScript, buildOutputDir: .app.buildOutputDir, measurements: .app.measurements}]')" >> $GITHUB_OUTPUT echo "deps=$(echo "$FRAMEWORKS" | jq -c '[.[] | select(.starter) | select(.starter.measurements | map(.type) | contains(["dependencies"])) | {name, displayName, package: .starter.package}]')" >> $GITHUB_OUTPUT - echo "spa=$(echo "$FRAMEWORKS" | jq -c '[.[] | select(.app) | select(.app.measurements | map(.type) | contains(["clientSideRendered"])) | {name, displayName, package: .app.package, buildScript: .app.buildScript, buildOutputDir: .app.buildOutputDir, measurements: .app.measurements}]')" >> $GITHUB_OUTPUT - echo "mpa=$(echo "$FRAMEWORKS" | jq -c '[.[] | select(.app) | select(.app.measurements | map(.type) | contains(["mpa"])) | {name, displayName, package: .app.package, buildScript: .app.buildScript, buildOutputDir: .app.buildOutputDir, measurements: .app.measurements}]')" >> $GITHUB_OUTPUT + echo "client-side-rendered=$(echo "$FRAMEWORKS" | jq -c '[.[] | select(.app) | select(.app.measurements | map(.type) | contains(["clientSideRendered"])) | {name, displayName, package: .app.package, buildScript: .app.buildScript, buildOutputDir: .app.buildOutputDir, measurements: .app.measurements}]')" >> $GITHUB_OUTPUT + echo "server-side-rendered=$(echo "$FRAMEWORKS" | jq -c '[.[] | select(.app) | select(.app.measurements | map(.type) | contains(["serverSideRendered"])) | {name, displayName, package: .app.package, buildScript: .app.buildScript, buildOutputDir: .app.buildOutputDir, measurements: .app.measurements}]')" >> $GITHUB_OUTPUT measure: needs: setup @@ -49,10 +49,10 @@ jobs: with: install-matrix: ${{ needs.setup.outputs.install-matrix }} build-matrix: ${{ needs.setup.outputs.build-matrix }} - ssr-matrix: ${{ needs.setup.outputs.ssr-matrix }} + ssr-request-throughput-matrix: ${{ needs.setup.outputs.ssr-request-throughput-matrix }} deps-matrix: ${{ needs.setup.outputs.deps-matrix }} - spa-matrix: ${{ needs.setup.outputs.spa-matrix }} - mpa-matrix: ${{ needs.setup.outputs.mpa-matrix }} + client-side-rendered-matrix: ${{ needs.setup.outputs.client-side-rendered-matrix }} + server-side-rendered-matrix: ${{ needs.setup.outputs.server-side-rendered-matrix }} generate-stats: needs: [setup, measure] diff --git a/.github/workflows/measure-framework.yml b/.github/workflows/measure-framework.yml index 8456f793..3b0b289b 100644 --- a/.github/workflows/measure-framework.yml +++ b/.github/workflows/measure-framework.yml @@ -11,8 +11,8 @@ on: description: 'JSON array of frameworks to measure build time' type: string required: true - ssr-matrix: - description: 'JSON array of frameworks to measure SSR performance' + ssr-request-throughput-matrix: + description: 'JSON array of frameworks to measure SSR request throughput performance' type: string required: true deps-matrix: @@ -20,13 +20,13 @@ on: type: string required: false default: '[]' - spa-matrix: - description: 'JSON array of frameworks to measure SPA paint and interaction performance' + client-side-rendered-matrix: + description: 'JSON array of frameworks to measure client-side rendered paint and interaction performance' type: string required: false default: '[]' - mpa-matrix: - description: 'JSON array of frameworks to measure MPA paint and interaction performance' + server-side-rendered-matrix: + description: 'JSON array of frameworks to measure server-side rendered paint and interaction performance' type: string required: false default: '[]' @@ -118,13 +118,13 @@ jobs: retention-days: 1 if-no-files-found: warn - measure-ssr: - if: inputs.ssr-matrix != '[]' + measure-ssr-request-throughput: + if: inputs.ssr-request-throughput-matrix != '[]' runs-on: depot-ubuntu-24.04 strategy: fail-fast: false matrix: - framework: ${{ fromJson(inputs.ssr-matrix) }} + framework: ${{ fromJson(inputs.ssr-request-throughput-matrix) }} steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -149,15 +149,15 @@ jobs: working-directory: ./packages/${{ matrix.framework.package }} run: pnpm build - - name: Run SSR benchmark - run: pnpm --filter @framework-tracker/stats-generator run:ssr ${{ matrix.framework.package }} + - name: Run SSR request throughput benchmark + run: pnpm --filter @framework-tracker/stats-generator run:ssr-request-throughput ${{ matrix.framework.package }} env: RUNNER_LABEL: ubuntu-latest - - name: Upload SSR stats + - name: Upload SSR request throughput stats uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: ssr-stats-${{ matrix.framework.name }} + name: ssr-request-throughput-stats-${{ matrix.framework.name }} path: packages/${{ matrix.framework.package }}/ci-stats.json retention-days: 1 if-no-files-found: error @@ -198,8 +198,8 @@ jobs: retention-days: 1 if-no-files-found: error - measure-spa: - if: inputs.spa-matrix != '[]' + measure-client-side-rendered: + if: inputs.client-side-rendered-matrix != '[]' runs-on: depot-ubuntu-24.04 container: image: mcr.microsoft.com/playwright:v1.49.0-noble @@ -207,7 +207,7 @@ jobs: strategy: fail-fast: false matrix: - framework: ${{ fromJson(inputs.spa-matrix) }} + framework: ${{ fromJson(inputs.client-side-rendered-matrix) }} steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -234,23 +234,23 @@ jobs: env: BUILD_MODE: spa - - name: Run SPA benchmark - run: pnpm --filter @framework-tracker/stats-generator run:spa ${{ matrix.framework.package }} + - name: Run client-side rendered benchmark + run: pnpm --filter @framework-tracker/stats-generator run:client-side-rendered ${{ matrix.framework.package }} env: PLAYWRIGHT_BROWSERS_PATH: /ms-playwright PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' RUNNER_LABEL: ubuntu-latest - - name: Upload SPA stats + - name: Upload client-side rendered stats uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: spa-stats-${{ matrix.framework.name }} + name: client-side-rendered-stats-${{ matrix.framework.name }} path: packages/${{ matrix.framework.package }}/ci-stats.json retention-days: 1 if-no-files-found: error - measure-mpa: - if: inputs.mpa-matrix != '[]' + measure-server-side-rendered: + if: inputs.server-side-rendered-matrix != '[]' runs-on: depot-ubuntu-24.04 container: image: mcr.microsoft.com/playwright:v1.49.0-noble @@ -258,7 +258,7 @@ jobs: strategy: fail-fast: false matrix: - framework: ${{ fromJson(inputs.mpa-matrix) }} + framework: ${{ fromJson(inputs.server-side-rendered-matrix) }} steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -283,17 +283,17 @@ jobs: working-directory: ./packages/${{ matrix.framework.package }} run: pnpm build - - name: Run MPA benchmark - run: pnpm --filter @framework-tracker/stats-generator run:mpa ${{ matrix.framework.package }} + - name: Run server-side rendered benchmark + run: pnpm --filter @framework-tracker/stats-generator run:server-side-rendered ${{ matrix.framework.package }} env: PLAYWRIGHT_BROWSERS_PATH: /ms-playwright PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' RUNNER_LABEL: ubuntu-latest - - name: Upload MPA stats + - name: Upload server-side rendered stats uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: mpa-stats-${{ matrix.framework.name }} + name: server-side-rendered-stats-${{ matrix.framework.name }} path: packages/${{ matrix.framework.package }}/ci-stats.json retention-days: 1 if-no-files-found: error diff --git a/.github/workflows/preview-stats.yml b/.github/workflows/preview-stats.yml index 7b590b90..2eb14b36 100644 --- a/.github/workflows/preview-stats.yml +++ b/.github/workflows/preview-stats.yml @@ -9,7 +9,7 @@ jobs: outputs: install-matrix: ${{ steps.detect.outputs.install }} build-matrix: ${{ steps.detect.outputs.build }} - ssr-matrix: ${{ steps.detect.outputs.ssr }} + ssr-request-throughput-matrix: ${{ steps.detect.outputs.ssr-request-throughput }} deps-matrix: ${{ steps.detect.outputs.deps }} framework-names: ${{ steps.detect.outputs.framework-names }} has-changes: ${{ steps.detect.outputs.has-changes }} @@ -45,7 +45,7 @@ jobs: echo "framework-names=[]" >> $GITHUB_OUTPUT echo "install=[]" >> $GITHUB_OUTPUT echo "build=[]" >> $GITHUB_OUTPUT - echo "ssr=[]" >> $GITHUB_OUTPUT + echo "ssr-request-throughput=[]" >> $GITHUB_OUTPUT exit 0 fi @@ -67,7 +67,7 @@ jobs: echo "install=$(echo "$FRAMEWORKS" | jq -c --argjson names "$NAMES_JSON" '[.[] | select(.name as $n | $names | contains([$n])) | select(.starter) | select(.starter.measurements | map(.type) | contains(["install"])) | {name, displayName, package: .starter.package, buildScript: .starter.buildScript, buildOutputDir: .starter.buildOutputDir, measurements: .starter.measurements}]')" >> $GITHUB_OUTPUT echo "build=$(echo "$FRAMEWORKS" | jq -c --argjson names "$NAMES_JSON" '[.[] | select(.name as $n | $names | contains([$n])) | select(.starter) | select(.starter.measurements | map(.type) | contains(["build"])) | {name, displayName, package: .starter.package, buildScript: .starter.buildScript, buildOutputDir: .starter.buildOutputDir, measurements: .starter.measurements}]')" >> $GITHUB_OUTPUT - echo "ssr=$(echo "$FRAMEWORKS" | jq -c --argjson names "$NAMES_JSON" '[.[] | select(.name as $n | $names | contains([$n])) | select(.app) | select(.app.measurements | map(.type) | contains(["ssr"])) | {name, displayName, package: .app.package, buildScript: .app.buildScript, buildOutputDir: .app.buildOutputDir, measurements: .app.measurements}]')" >> $GITHUB_OUTPUT + echo "ssr-request-throughput=$(echo "$FRAMEWORKS" | jq -c --argjson names "$NAMES_JSON" '[.[] | select(.name as $n | $names | contains([$n])) | select(.app) | select(.app.measurements | map(.type) | contains(["ssrRequestThroughput"])) | {name, displayName, package: .app.package, buildScript: .app.buildScript, buildOutputDir: .app.buildOutputDir, measurements: .app.measurements}]')" >> $GITHUB_OUTPUT echo "deps=$(echo "$FRAMEWORKS" | jq -c --argjson names "$NAMES_JSON" '[.[] | select(.name as $n | $names | contains([$n])) | select(.starter) | select(.starter.measurements | map(.type) | contains(["dependencies"])) | {name, displayName, package: .starter.package}]')" >> $GITHUB_OUTPUT measure: @@ -77,7 +77,7 @@ jobs: with: install-matrix: ${{ needs.setup.outputs.install-matrix }} build-matrix: ${{ needs.setup.outputs.build-matrix }} - ssr-matrix: ${{ needs.setup.outputs.ssr-matrix }} + ssr-request-throughput-matrix: ${{ needs.setup.outputs.ssr-request-throughput-matrix }} deps-matrix: ${{ needs.setup.outputs.deps-matrix }} preview-comment: diff --git a/.github/workflows/validate-stats.yml b/.github/workflows/validate-stats.yml index 1dfb43ed..f6e564ca 100644 --- a/.github/workflows/validate-stats.yml +++ b/.github/workflows/validate-stats.yml @@ -42,14 +42,14 @@ jobs: run: | set -e - echo "=== Running SSR benchmarks ===" + echo "=== Running SSR request throughput benchmarks ===" FRAMEWORKS=$(cat .github/frameworks.json) echo "$FRAMEWORKS" | jq -c '.[] | select(.app)' | while read -r framework; do PKG=$(echo "$framework" | jq -r '.app.package') echo "Building $PKG..." (cd packages/$PKG && pnpm build) - echo "Running SSR benchmark for $PKG..." - pnpm --filter @framework-tracker/stats-generator run:ssr $PKG + echo "Running SSR request throughput benchmark for $PKG..." + pnpm --filter @framework-tracker/stats-generator run:ssr-request-throughput $PKG done echo "" @@ -73,25 +73,25 @@ jobs: done echo "" - echo "=== Running SPA benchmarks ===" + echo "=== Running client-side rendered benchmarks ===" FRAMEWORKS=$(cat .github/frameworks.json) echo "$FRAMEWORKS" | jq -c '.[] | select(.app) | select(.app.measurements | map(.type) | contains(["clientSideRendered"]))' | while read -r framework; do PKG=$(echo "$framework" | jq -r '.app.package') - echo "Building SPA for $PKG..." + echo "Building client-side rendered app for $PKG..." (cd packages/$PKG && BUILD_MODE=spa pnpm build) - echo "Running SPA benchmark for $PKG..." - pnpm --filter @framework-tracker/stats-generator run:spa $PKG + echo "Running client-side rendered benchmark for $PKG..." + pnpm --filter @framework-tracker/stats-generator run:client-side-rendered $PKG done echo "" - echo "=== Running MPA benchmarks ===" + echo "=== Running server-side rendered benchmarks ===" FRAMEWORKS=$(cat .github/frameworks.json) - echo "$FRAMEWORKS" | jq -c '.[] | select(.app) | select(.app.measurements | map(.type) | contains(["mpa"]))' | while read -r framework; do + echo "$FRAMEWORKS" | jq -c '.[] | select(.app) | select(.app.measurements | map(.type) | contains(["serverSideRendered"]))' | while read -r framework; do PKG=$(echo "$framework" | jq -r '.app.package') - echo "Building MPA for $PKG..." + echo "Building server-side rendered app for $PKG..." (cd packages/$PKG && pnpm build) - echo "Running MPA benchmark for $PKG..." - pnpm --filter @framework-tracker/stats-generator run:mpa $PKG + echo "Running server-side rendered benchmark for $PKG..." + pnpm --filter @framework-tracker/stats-generator run:server-side-rendered $PKG done echo "" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1a55f228..03eaaa7d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,7 +79,7 @@ All frameworks are configured in `.github/frameworks.json`. Each entry specifies "package": "app-astro", "buildScript": "build:app-astro", "buildOutputDir": "dist", - "measurements": [{ "type": "ssr" }] + "measurements": [{ "type": "ssrRequestThroughput" }] } }, ``` diff --git a/Dockerfile b/Dockerfile index 54af4155..22cac215 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ USER node WORKDIR /app CMD [ "node", "src/cwv/index.ts" ] -FROM mcr.microsoft.com/playwright:v1.49.0-noble AS spa-benchmark +FROM mcr.microsoft.com/playwright:v1.49.0-noble AS client-side-rendered-benchmark ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN npm install -g pnpm diff --git a/Roadmap.md b/Roadmap.md index a9c0c796..f18e6fd5 100644 --- a/Roadmap.md +++ b/Roadmap.md @@ -6,7 +6,7 @@ To make it clearer what we are actively working on, here is a breakdown of our c ## Current Focus Areas -- **SPA**: Adding a SPA test and metrics for each metaframework. +- **Client Side Rendered**: Adding a client-side rendered route test and metrics for each metaframework. - **In the Wild Data**: Pull in real world data for each framework from the HTTP Archive - **Bundle Analysis**: Scanning and checking output of each metaframework looking for things like use of modern web APIs and redundant dependencies or polyfills. diff --git a/packages/app-astro/ci-stats.json b/packages/app-astro/ci-stats.json index 763a0d59..e4c7a10a 100644 --- a/packages/app-astro/ci-stats.json +++ b/packages/app-astro/ci-stats.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "5.16.15", - "ssrOpsPerSec": 570, - "ssrAvgLatencyMs": 1.769, - "ssrMedianLatencyMs": 1.745, - "ssrSamples": 5653, - "ssrBodySizeKb": 99.86, - "ssrDuplicationFactor": 1, - "mpaFirstPaintMs": 68.8, - "mpaFCPMs": 68.87, - "mpaINPMs": 3.41, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 92.4, "fcpMs": 92.3, "inpMs": 6.29, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 570, + "avgLatencyMs": 1.769, + "medianLatencyMs": 1.745, + "samples": 5653, + "bodySizeKb": 99.86, + "duplicationFactor": 1 + }, + "serverSideRenderedTests": { + "firstPaintMs": 68.8, + "fcpMs": 68.87, + "inpMs": 3.41, + "runs": 5 } } diff --git a/packages/app-astro/src/components/ClientSideRenderedDetail.tsx b/packages/app-astro/src/components/ClientSideRenderedDetail.tsx new file mode 100644 index 00000000..8955f968 --- /dev/null +++ b/packages/app-astro/src/components/ClientSideRenderedDetail.tsx @@ -0,0 +1,3 @@ +export default function ClientSideRenderedDetail({ id }: { id?: string }) { + return

{id}

+} diff --git a/packages/app-astro/src/components/SpaPage.tsx b/packages/app-astro/src/components/ClientSideRenderedPage.tsx similarity index 81% rename from packages/app-astro/src/components/SpaPage.tsx rename to packages/app-astro/src/components/ClientSideRenderedPage.tsx index abb7a384..816e10c2 100644 --- a/packages/app-astro/src/components/SpaPage.tsx +++ b/packages/app-astro/src/components/ClientSideRenderedPage.tsx @@ -9,7 +9,7 @@ function generateData(): Entry[] { })) } -export default function SpaPage() { +export default function ClientSideRenderedPage() { const [entries] = useState(generateData) return ( @@ -20,7 +20,7 @@ export default function SpaPage() { {entry.id} {entry.name} - View → + View → ))} diff --git a/packages/app-astro/src/components/SpaDetail.tsx b/packages/app-astro/src/components/SpaDetail.tsx deleted file mode 100644 index 252b211d..00000000 --- a/packages/app-astro/src/components/SpaDetail.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function SpaDetail({ id }: { id?: string }) { - return

{id}

-} diff --git a/packages/app-astro/src/pages/spa.astro b/packages/app-astro/src/pages/client-side-rendered.astro similarity index 55% rename from packages/app-astro/src/pages/spa.astro rename to packages/app-astro/src/pages/client-side-rendered.astro index 7c975b9f..d6263a2d 100644 --- a/packages/app-astro/src/pages/spa.astro +++ b/packages/app-astro/src/pages/client-side-rendered.astro @@ -1,16 +1,16 @@ --- import { ClientRouter } from 'astro:transitions' -import SpaPage from '../components/SpaPage' +import ClientSideRenderedPage from '../components/ClientSideRenderedPage' --- - Astro SPA Benchmark + Astro Client Side Rendered Benchmark - + diff --git a/packages/app-astro/src/pages/client-side-rendered/[id].astro b/packages/app-astro/src/pages/client-side-rendered/[id].astro new file mode 100644 index 00000000..bf1422a3 --- /dev/null +++ b/packages/app-astro/src/pages/client-side-rendered/[id].astro @@ -0,0 +1,16 @@ +--- +import ClientSideRenderedDetail from '../../components/ClientSideRenderedDetail' + +const { id } = Astro.params +--- + + + + + + Astro Client Side Rendered Detail + + + + + diff --git a/packages/app-astro/src/pages/mpa.astro b/packages/app-astro/src/pages/server-side-rendered.astro similarity index 79% rename from packages/app-astro/src/pages/mpa.astro rename to packages/app-astro/src/pages/server-side-rendered.astro index 1fc1a560..c1945291 100644 --- a/packages/app-astro/src/pages/mpa.astro +++ b/packages/app-astro/src/pages/server-side-rendered.astro @@ -7,7 +7,7 @@ const entries = await testData() - Astro MPA Benchmark + Astro Server Side Rendered Benchmark @@ -18,7 +18,7 @@ const entries = await testData() )) diff --git a/packages/app-astro/src/pages/mpa/[id].astro b/packages/app-astro/src/pages/server-side-rendered/[id].astro similarity index 80% rename from packages/app-astro/src/pages/mpa/[id].astro rename to packages/app-astro/src/pages/server-side-rendered/[id].astro index 0ad006fd..4a6f21d0 100644 --- a/packages/app-astro/src/pages/mpa/[id].astro +++ b/packages/app-astro/src/pages/server-side-rendered/[id].astro @@ -6,7 +6,7 @@ const { id } = Astro.params - Astro MPA Detail + Astro Server Side Rendered Detail

{id}

diff --git a/packages/app-astro/src/pages/spa/[id].astro b/packages/app-astro/src/pages/spa/[id].astro deleted file mode 100644 index f9728796..00000000 --- a/packages/app-astro/src/pages/spa/[id].astro +++ /dev/null @@ -1,16 +0,0 @@ ---- -import SpaDetail from '../../components/SpaDetail' - -const { id } = Astro.params ---- - - - - - - Astro SPA Detail - - - - - diff --git a/packages/app-astro/stats/5.16.15.json b/packages/app-astro/stats/5.16.15.json index 763a0d59..e4c7a10a 100644 --- a/packages/app-astro/stats/5.16.15.json +++ b/packages/app-astro/stats/5.16.15.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "5.16.15", - "ssrOpsPerSec": 570, - "ssrAvgLatencyMs": 1.769, - "ssrMedianLatencyMs": 1.745, - "ssrSamples": 5653, - "ssrBodySizeKb": 99.86, - "ssrDuplicationFactor": 1, - "mpaFirstPaintMs": 68.8, - "mpaFCPMs": 68.87, - "mpaINPMs": 3.41, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 92.4, "fcpMs": 92.3, "inpMs": 6.29, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 570, + "avgLatencyMs": 1.769, + "medianLatencyMs": 1.745, + "samples": 5653, + "bodySizeKb": 99.86, + "duplicationFactor": 1 + }, + "serverSideRenderedTests": { + "firstPaintMs": 68.8, + "fcpMs": 68.87, + "inpMs": 3.41, + "runs": 5 } } diff --git a/packages/app-baseline-html/ci-stats.json b/packages/app-baseline-html/ci-stats.json index 4ae69801..1ef92a42 100644 --- a/packages/app-baseline-html/ci-stats.json +++ b/packages/app-baseline-html/ci-stats.json @@ -1,10 +1,12 @@ { "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", - "ssrOpsPerSec": 848, - "ssrAvgLatencyMs": 1.202, - "ssrMedianLatencyMs": 1.202, - "ssrSamples": 8319, - "ssrBodySizeKb": 96.81, - "ssrDuplicationFactor": 1 + "ssrRequestThroughputTests": { + "opsPerSec": 848, + "avgLatencyMs": 1.202, + "medianLatencyMs": 1.202, + "samples": 8319, + "bodySizeKb": 96.81, + "duplicationFactor": 1 + } } diff --git a/packages/app-mastro/ci-stats.json b/packages/app-mastro/ci-stats.json index 3979059d..b1fceb38 100644 --- a/packages/app-mastro/ci-stats.json +++ b/packages/app-mastro/ci-stats.json @@ -1,10 +1,12 @@ { "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", - "ssrOpsPerSec": 502, - "ssrAvgLatencyMs": 2.013, - "ssrMedianLatencyMs": 1.986, - "ssrSamples": 4967, - "ssrBodySizeKb": 181.95, - "ssrDuplicationFactor": 1 + "ssrRequestThroughputTests": { + "opsPerSec": 502, + "avgLatencyMs": 2.013, + "medianLatencyMs": 1.986, + "samples": 4967, + "bodySizeKb": 181.95, + "duplicationFactor": 1 + } } diff --git a/packages/app-next-js/app/spa/SpaTable.tsx b/packages/app-next-js/app/client-side-rendered/ClientSideRenderedTable.tsx similarity index 81% rename from packages/app-next-js/app/spa/SpaTable.tsx rename to packages/app-next-js/app/client-side-rendered/ClientSideRenderedTable.tsx index 6ad220a1..238ef8ad 100644 --- a/packages/app-next-js/app/spa/SpaTable.tsx +++ b/packages/app-next-js/app/client-side-rendered/ClientSideRenderedTable.tsx @@ -12,7 +12,7 @@ function generateData(): Entry[] { })) } -export default function SpaTable() { +export default function ClientSideRenderedTable() { const [entries] = useState(generateData) return ( @@ -23,7 +23,7 @@ export default function SpaTable() { ))} diff --git a/packages/app-next-js/app/spa/[id]/page.tsx b/packages/app-next-js/app/client-side-rendered/[id]/page.tsx similarity index 72% rename from packages/app-next-js/app/spa/[id]/page.tsx rename to packages/app-next-js/app/client-side-rendered/[id]/page.tsx index 807c02a4..477ae378 100644 --- a/packages/app-next-js/app/spa/[id]/page.tsx +++ b/packages/app-next-js/app/client-side-rendered/[id]/page.tsx @@ -2,7 +2,7 @@ import { useParams } from 'next/navigation' -export default function SpaDetailPage() { +export default function ClientSideRenderedDetailPage() { const params = useParams<{ id: string }>() return

{params.id}

diff --git a/packages/app-next-js/app/client-side-rendered/page.tsx b/packages/app-next-js/app/client-side-rendered/page.tsx new file mode 100644 index 00000000..1a453073 --- /dev/null +++ b/packages/app-next-js/app/client-side-rendered/page.tsx @@ -0,0 +1,12 @@ +'use client' + +import dynamic from 'next/dynamic' + +const ClientSideRenderedTable = dynamic( + () => import('./ClientSideRenderedTable'), + { ssr: false }, +) + +export default function ClientSideRenderedPage() { + return +} diff --git a/packages/app-next-js/app/mpa/[id]/page.tsx b/packages/app-next-js/app/server-side-rendered/[id]/page.tsx similarity index 60% rename from packages/app-next-js/app/mpa/[id]/page.tsx rename to packages/app-next-js/app/server-side-rendered/[id]/page.tsx index 54795502..9df5f140 100644 --- a/packages/app-next-js/app/mpa/[id]/page.tsx +++ b/packages/app-next-js/app/server-side-rendered/[id]/page.tsx @@ -2,7 +2,7 @@ interface Props { params: Promise<{ id: string }> } -export default async function MpaDetailPage({ params }: Props) { +export default async function ServerSideRenderedDetailPage({ params }: Props) { const { id } = await params return

{id}

diff --git a/packages/app-next-js/app/mpa/page.tsx b/packages/app-next-js/app/server-side-rendered/page.tsx similarity index 75% rename from packages/app-next-js/app/mpa/page.tsx rename to packages/app-next-js/app/server-side-rendered/page.tsx index ed07276c..0866057a 100644 --- a/packages/app-next-js/app/mpa/page.tsx +++ b/packages/app-next-js/app/server-side-rendered/page.tsx @@ -3,7 +3,7 @@ import { testData } from '../../../testdata/src/ssr' export const dynamic = 'force-dynamic' -export default async function MpaPage() { +export default async function ServerSideRenderedPage() { const entries = await testData() return ( @@ -14,7 +14,7 @@ export default async function MpaPage() {
))} diff --git a/packages/app-next-js/app/spa/page.tsx b/packages/app-next-js/app/spa/page.tsx deleted file mode 100644 index 3d9b5e67..00000000 --- a/packages/app-next-js/app/spa/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -'use client' - -import dynamic from 'next/dynamic' - -const SpaTable = dynamic(() => import('./SpaTable'), { ssr: false }) - -export default function SpaPage() { - return -} diff --git a/packages/app-next-js/ci-stats.json b/packages/app-next-js/ci-stats.json index 7fd8f844..2795e3d0 100644 --- a/packages/app-next-js/ci-stats.json +++ b/packages/app-next-js/ci-stats.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "16.1.1", - "ssrOpsPerSec": 215, - "ssrAvgLatencyMs": 4.78, - "ssrMedianLatencyMs": 4.812, - "ssrSamples": 2092, - "ssrBodySizeKb": 199.11, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 124.2, - "mpaFCPMs": 124.06, - "mpaINPMs": 0, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 348.6, "fcpMs": 348.55, "inpMs": 16.28, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 215, + "avgLatencyMs": 4.78, + "medianLatencyMs": 4.812, + "samples": 2092, + "bodySizeKb": 199.11, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 124.2, + "fcpMs": 124.06, + "inpMs": 0, + "runs": 5 } } diff --git a/packages/app-next-js/stats/16.1.1.json b/packages/app-next-js/stats/16.1.1.json index 7fd8f844..2795e3d0 100644 --- a/packages/app-next-js/stats/16.1.1.json +++ b/packages/app-next-js/stats/16.1.1.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "16.1.1", - "ssrOpsPerSec": 215, - "ssrAvgLatencyMs": 4.78, - "ssrMedianLatencyMs": 4.812, - "ssrSamples": 2092, - "ssrBodySizeKb": 199.11, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 124.2, - "mpaFCPMs": 124.06, - "mpaINPMs": 0, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 348.6, "fcpMs": 348.55, "inpMs": 16.28, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 215, + "avgLatencyMs": 4.78, + "medianLatencyMs": 4.812, + "samples": 2092, + "bodySizeKb": 199.11, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 124.2, + "fcpMs": 124.06, + "inpMs": 0, + "runs": 5 } } diff --git a/packages/app-nuxt/app/pages/spa/[id].vue b/packages/app-nuxt/app/pages/client-side-rendered/[id].vue similarity index 100% rename from packages/app-nuxt/app/pages/spa/[id].vue rename to packages/app-nuxt/app/pages/client-side-rendered/[id].vue diff --git a/packages/app-nuxt/app/pages/spa/index.vue b/packages/app-nuxt/app/pages/client-side-rendered/index.vue similarity index 84% rename from packages/app-nuxt/app/pages/spa/index.vue rename to packages/app-nuxt/app/pages/client-side-rendered/index.vue index 0f15e260..10244d02 100644 --- a/packages/app-nuxt/app/pages/spa/index.vue +++ b/packages/app-nuxt/app/pages/client-side-rendered/index.vue @@ -16,7 +16,7 @@ const entries: Entry[] = Array.from({ length: 1000 }, () => ({ diff --git a/packages/app-nuxt/app/pages/mpa/[id].vue b/packages/app-nuxt/app/pages/server-side-rendered/[id].vue similarity index 100% rename from packages/app-nuxt/app/pages/mpa/[id].vue rename to packages/app-nuxt/app/pages/server-side-rendered/[id].vue diff --git a/packages/app-nuxt/app/pages/mpa/index.vue b/packages/app-nuxt/app/pages/server-side-rendered/index.vue similarity index 82% rename from packages/app-nuxt/app/pages/mpa/index.vue rename to packages/app-nuxt/app/pages/server-side-rendered/index.vue index 1e87d4d9..6a23636e 100644 --- a/packages/app-nuxt/app/pages/mpa/index.vue +++ b/packages/app-nuxt/app/pages/server-side-rendered/index.vue @@ -11,7 +11,7 @@ const { data } = await useAsyncData(() => testData(), { deep: false }) diff --git a/packages/app-nuxt/ci-stats.json b/packages/app-nuxt/ci-stats.json index 39f004e2..2128209a 100644 --- a/packages/app-nuxt/ci-stats.json +++ b/packages/app-nuxt/ci-stats.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "4.2.2", - "ssrOpsPerSec": 384, - "ssrAvgLatencyMs": 2.664, - "ssrMedianLatencyMs": 2.544, - "ssrSamples": 3755, - "ssrBodySizeKb": 201.26, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 96.2, - "mpaFCPMs": 96.23, - "mpaINPMs": 13.72, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 92.2, "fcpMs": 92.33, "inpMs": 10.13, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 384, + "avgLatencyMs": 2.664, + "medianLatencyMs": 2.544, + "samples": 3755, + "bodySizeKb": 201.26, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 96.2, + "fcpMs": 96.23, + "inpMs": 13.72, + "runs": 5 } } diff --git a/packages/app-nuxt/stats/4.2.2.json b/packages/app-nuxt/stats/4.2.2.json index 39f004e2..2128209a 100644 --- a/packages/app-nuxt/stats/4.2.2.json +++ b/packages/app-nuxt/stats/4.2.2.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "4.2.2", - "ssrOpsPerSec": 384, - "ssrAvgLatencyMs": 2.664, - "ssrMedianLatencyMs": 2.544, - "ssrSamples": 3755, - "ssrBodySizeKb": 201.26, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 96.2, - "mpaFCPMs": 96.23, - "mpaINPMs": 13.72, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 92.2, "fcpMs": 92.33, "inpMs": 10.13, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 384, + "avgLatencyMs": 2.664, + "medianLatencyMs": 2.544, + "samples": 3755, + "bodySizeKb": 201.26, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 96.2, + "fcpMs": 96.23, + "inpMs": 13.72, + "runs": 5 } } diff --git a/packages/app-react-router/app/routes.ts b/packages/app-react-router/app/routes.ts index 49464a81..dc2c1fe9 100644 --- a/packages/app-react-router/app/routes.ts +++ b/packages/app-react-router/app/routes.ts @@ -1,15 +1,18 @@ import { type RouteConfig, index, route } from '@react-router/dev/routes' -const isSpa = process.env.BUILD_MODE === 'spa' +const isClientSideRendered = process.env.BUILD_MODE === 'spa' export default [ - ...(isSpa ? [] : [index('routes/home.tsx')]), - route('/spa', 'routes/spa.tsx'), - route('/spa/:id', 'routes/spa.detail.tsx'), - ...(isSpa + ...(isClientSideRendered ? [] : [index('routes/home.tsx')]), + route('/client-side-rendered', 'routes/client-side-rendered.tsx'), + route('/client-side-rendered/:id', 'routes/client-side-rendered.detail.tsx'), + ...(isClientSideRendered ? [] : [ - route('/mpa', 'routes/mpa.tsx'), - route('/mpa/:id', 'routes/mpa.detail.tsx'), + route('/server-side-rendered', 'routes/server-side-rendered.tsx'), + route( + '/server-side-rendered/:id', + 'routes/server-side-rendered.detail.tsx', + ), ]), ] satisfies RouteConfig diff --git a/packages/app-react-router/app/routes/spa.detail.tsx b/packages/app-react-router/app/routes/client-side-rendered.detail.tsx similarity index 65% rename from packages/app-react-router/app/routes/spa.detail.tsx rename to packages/app-react-router/app/routes/client-side-rendered.detail.tsx index 1c71cc8b..0be5ef5d 100644 --- a/packages/app-react-router/app/routes/spa.detail.tsx +++ b/packages/app-react-router/app/routes/client-side-rendered.detail.tsx @@ -1,6 +1,6 @@ import { useParams } from 'react-router' -export default function SpaDetailPage() { +export default function ClientSideRenderedDetailPage() { const { id } = useParams() return

{id}

diff --git a/packages/app-react-router/app/routes/spa.tsx b/packages/app-react-router/app/routes/client-side-rendered.tsx similarity index 81% rename from packages/app-react-router/app/routes/spa.tsx rename to packages/app-react-router/app/routes/client-side-rendered.tsx index a39268be..8476eb92 100644 --- a/packages/app-react-router/app/routes/spa.tsx +++ b/packages/app-react-router/app/routes/client-side-rendered.tsx @@ -10,7 +10,7 @@ function generateData(): Entry[] { })) } -export default function SpaPage() { +export default function ClientSideRenderedPage() { const [entries] = useState(generateData) return ( @@ -21,7 +21,7 @@ export default function SpaPage() { ))} diff --git a/packages/app-react-router/app/routes/mpa.detail.tsx b/packages/app-react-router/app/routes/mpa.detail.tsx deleted file mode 100644 index f56f0119..00000000 --- a/packages/app-react-router/app/routes/mpa.detail.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import type { Route } from './+types/mpa.detail' - -export async function loader({ params }: Route.LoaderArgs) { - const id = params.id - return { id } -} - -export default function MpaDetailPage({ loaderData }: Route.ComponentProps) { - return

{loaderData.id}

-} diff --git a/packages/app-react-router/app/routes/server-side-rendered.detail.tsx b/packages/app-react-router/app/routes/server-side-rendered.detail.tsx new file mode 100644 index 00000000..3d808b16 --- /dev/null +++ b/packages/app-react-router/app/routes/server-side-rendered.detail.tsx @@ -0,0 +1,12 @@ +import type { Route } from './+types/server-side-rendered.detail' + +export async function loader({ params }: Route.LoaderArgs) { + const id = params.id + return { id } +} + +export default function ServerSideRenderedDetailPage({ + loaderData, +}: Route.ComponentProps) { + return

{loaderData.id}

+} diff --git a/packages/app-react-router/app/routes/mpa.tsx b/packages/app-react-router/app/routes/server-side-rendered.tsx similarity index 66% rename from packages/app-react-router/app/routes/mpa.tsx rename to packages/app-react-router/app/routes/server-side-rendered.tsx index cc815baa..f40cbffc 100644 --- a/packages/app-react-router/app/routes/mpa.tsx +++ b/packages/app-react-router/app/routes/server-side-rendered.tsx @@ -1,13 +1,15 @@ import { Link } from 'react-router' import { testData } from '../../../testdata/src/ssr' -import type { Route } from './+types/mpa' +import type { Route } from './+types/server-side-rendered' export async function loader() { const data = await testData() return { data } } -export default function MpaPage({ loaderData }: Route.ComponentProps) { +export default function ServerSideRenderedPage({ + loaderData, +}: Route.ComponentProps) { return (
{entry.id} {entry.name} - View → + View →
{entry.id} {entry.name} - View → + View →
{entry.id} {entry.name} - View → + View →
{{ entry.id }} {{ entry.name }} - View → + View →
{{ entry.id }} {{ entry.name }} - View → + View →
{entry.id} {entry.name} - View → + View →
@@ -16,7 +18,7 @@ export default function MpaPage({ loaderData }: Route.ComponentProps) { ))} diff --git a/packages/app-react-router/ci-stats.json b/packages/app-react-router/ci-stats.json index be77a679..68a2010c 100644 --- a/packages/app-react-router/ci-stats.json +++ b/packages/app-react-router/ci-stats.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "7.10.1", - "ssrOpsPerSec": 64, - "ssrAvgLatencyMs": 15.528, - "ssrMedianLatencyMs": 0, - "ssrSamples": 644, - "ssrBodySizeKb": 211.14, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 141, - "mpaFCPMs": 140.92, - "mpaINPMs": 2.86, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 128.6, "fcpMs": 128.5, "inpMs": 15.03, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 64, + "avgLatencyMs": 15.528, + "medianLatencyMs": 0, + "samples": 644, + "bodySizeKb": 211.14, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 141, + "fcpMs": 140.92, + "inpMs": 2.86, + "runs": 5 } } diff --git a/packages/app-react-router/stats/7.10.1.json b/packages/app-react-router/stats/7.10.1.json index be77a679..68a2010c 100644 --- a/packages/app-react-router/stats/7.10.1.json +++ b/packages/app-react-router/stats/7.10.1.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "7.10.1", - "ssrOpsPerSec": 64, - "ssrAvgLatencyMs": 15.528, - "ssrMedianLatencyMs": 0, - "ssrSamples": 644, - "ssrBodySizeKb": 211.14, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 141, - "mpaFCPMs": 140.92, - "mpaINPMs": 2.86, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 128.6, "fcpMs": 128.5, "inpMs": 15.03, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 64, + "avgLatencyMs": 15.528, + "medianLatencyMs": 0, + "samples": 644, + "bodySizeKb": 211.14, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 141, + "fcpMs": 140.92, + "inpMs": 2.86, + "runs": 5 } } diff --git a/packages/app-solid-start/ci-stats.json b/packages/app-solid-start/ci-stats.json index 36cb3b6e..28474f90 100644 --- a/packages/app-solid-start/ci-stats.json +++ b/packages/app-solid-start/ci-stats.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "1.2.1", - "ssrOpsPerSec": 404, - "ssrAvgLatencyMs": 2.616, - "ssrMedianLatencyMs": 2.478, - "ssrSamples": 3823, - "ssrBodySizeKb": 227.77, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 80, - "mpaFCPMs": 79.87, - "mpaINPMs": 11.96, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 92.2, "fcpMs": 91.91, "inpMs": 14.89, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 404, + "avgLatencyMs": 2.616, + "medianLatencyMs": 2.478, + "samples": 3823, + "bodySizeKb": 227.77, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 80, + "fcpMs": 79.87, + "inpMs": 11.96, + "runs": 5 } } diff --git a/packages/app-solid-start/src/routes/spa/[id].tsx b/packages/app-solid-start/src/routes/client-side-rendered/[id].tsx similarity index 71% rename from packages/app-solid-start/src/routes/spa/[id].tsx rename to packages/app-solid-start/src/routes/client-side-rendered/[id].tsx index 338d061c..e6714949 100644 --- a/packages/app-solid-start/src/routes/spa/[id].tsx +++ b/packages/app-solid-start/src/routes/client-side-rendered/[id].tsx @@ -2,7 +2,7 @@ import { useParams } from '@solidjs/router' export const ssr = false -export default function SpaDetailPage() { +export default function ClientSideRenderedDetailPage() { const params = useParams() return

{params.id}

diff --git a/packages/app-solid-start/src/routes/spa/index.tsx b/packages/app-solid-start/src/routes/client-side-rendered/index.tsx similarity index 81% rename from packages/app-solid-start/src/routes/spa/index.tsx rename to packages/app-solid-start/src/routes/client-side-rendered/index.tsx index 672f0147..49984dd9 100644 --- a/packages/app-solid-start/src/routes/spa/index.tsx +++ b/packages/app-solid-start/src/routes/client-side-rendered/index.tsx @@ -10,7 +10,7 @@ const entries: Entry[] = Array.from({ length: 1000 }, () => ({ name: crypto.randomUUID(), })) -export default function SpaPage() { +export default function ClientSideRenderedPage() { return (
{entry.id} {entry.name} - View → + View →
@@ -20,7 +20,7 @@ export default function SpaPage() { )} diff --git a/packages/app-solid-start/src/routes/mpa/[id].tsx b/packages/app-solid-start/src/routes/server-side-rendered/[id].tsx similarity index 67% rename from packages/app-solid-start/src/routes/mpa/[id].tsx rename to packages/app-solid-start/src/routes/server-side-rendered/[id].tsx index cdaa3626..cbd1d658 100644 --- a/packages/app-solid-start/src/routes/mpa/[id].tsx +++ b/packages/app-solid-start/src/routes/server-side-rendered/[id].tsx @@ -1,6 +1,6 @@ import { useParams } from '@solidjs/router' -export default function MpaDetailPage() { +export default function ServerSideRenderedDetailPage() { const params = useParams() return

{params.id}

diff --git a/packages/app-solid-start/src/routes/mpa/index.tsx b/packages/app-solid-start/src/routes/server-side-rendered/index.tsx similarity index 79% rename from packages/app-solid-start/src/routes/mpa/index.tsx rename to packages/app-solid-start/src/routes/server-side-rendered/index.tsx index 25bd9c62..1e823059 100644 --- a/packages/app-solid-start/src/routes/mpa/index.tsx +++ b/packages/app-solid-start/src/routes/server-side-rendered/index.tsx @@ -5,13 +5,13 @@ import { testData } from '../../../../testdata/src/ssr' const getData = query(async () => { 'use server' return await testData() -}, 'mpa-data') +}, 'server-side-rendered-data') export const route = { load: () => getData(), } -export default function MpaPage() { +export default function ServerSideRenderedPage() { const data = createAsync(() => getData()) return ( @@ -23,7 +23,7 @@ export default function MpaPage() { )} diff --git a/packages/app-solid-start/stats/1.2.1.json b/packages/app-solid-start/stats/1.2.1.json index 36cb3b6e..28474f90 100644 --- a/packages/app-solid-start/stats/1.2.1.json +++ b/packages/app-solid-start/stats/1.2.1.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "1.2.1", - "ssrOpsPerSec": 404, - "ssrAvgLatencyMs": 2.616, - "ssrMedianLatencyMs": 2.478, - "ssrSamples": 3823, - "ssrBodySizeKb": 227.77, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 80, - "mpaFCPMs": 79.87, - "mpaINPMs": 11.96, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 92.2, "fcpMs": 91.91, "inpMs": 14.89, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 404, + "avgLatencyMs": 2.616, + "medianLatencyMs": 2.478, + "samples": 3823, + "bodySizeKb": 227.77, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 80, + "fcpMs": 79.87, + "inpMs": 11.96, + "runs": 5 } } diff --git a/packages/app-sveltekit/ci-stats.json b/packages/app-sveltekit/ci-stats.json index c953d1f9..8c9f920b 100644 --- a/packages/app-sveltekit/ci-stats.json +++ b/packages/app-sveltekit/ci-stats.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "2.49.4", - "ssrOpsPerSec": 437, - "ssrAvgLatencyMs": 2.337, - "ssrMedianLatencyMs": 2.221, - "ssrSamples": 4279, - "ssrBodySizeKb": 183.55, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 72.4, - "mpaFCPMs": 72.44, - "mpaINPMs": 0.45, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 106.6, "fcpMs": 106.59, "inpMs": 13.96, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 437, + "avgLatencyMs": 2.337, + "medianLatencyMs": 2.221, + "samples": 4279, + "bodySizeKb": 183.55, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 72.4, + "fcpMs": 72.44, + "inpMs": 0.45, + "runs": 5 } } diff --git a/packages/app-sveltekit/src/routes/spa/+page.svelte b/packages/app-sveltekit/src/routes/client-side-rendered/+page.svelte similarity index 83% rename from packages/app-sveltekit/src/routes/spa/+page.svelte rename to packages/app-sveltekit/src/routes/client-side-rendered/+page.svelte index 389d3234..e6a8dc0c 100644 --- a/packages/app-sveltekit/src/routes/spa/+page.svelte +++ b/packages/app-sveltekit/src/routes/client-side-rendered/+page.svelte @@ -13,7 +13,7 @@ - + {/each} diff --git a/packages/app-sveltekit/src/routes/spa/+page.ts b/packages/app-sveltekit/src/routes/client-side-rendered/+page.ts similarity index 100% rename from packages/app-sveltekit/src/routes/spa/+page.ts rename to packages/app-sveltekit/src/routes/client-side-rendered/+page.ts diff --git a/packages/app-sveltekit/src/routes/spa/[id]/+page.svelte b/packages/app-sveltekit/src/routes/client-side-rendered/[id]/+page.svelte similarity index 100% rename from packages/app-sveltekit/src/routes/spa/[id]/+page.svelte rename to packages/app-sveltekit/src/routes/client-side-rendered/[id]/+page.svelte diff --git a/packages/app-sveltekit/src/routes/spa/[id]/+page.ts b/packages/app-sveltekit/src/routes/client-side-rendered/[id]/+page.ts similarity index 100% rename from packages/app-sveltekit/src/routes/spa/[id]/+page.ts rename to packages/app-sveltekit/src/routes/client-side-rendered/[id]/+page.ts diff --git a/packages/app-sveltekit/src/routes/mpa/+page.server.ts b/packages/app-sveltekit/src/routes/server-side-rendered/+page.server.ts similarity index 100% rename from packages/app-sveltekit/src/routes/mpa/+page.server.ts rename to packages/app-sveltekit/src/routes/server-side-rendered/+page.server.ts diff --git a/packages/app-sveltekit/src/routes/mpa/+page.svelte b/packages/app-sveltekit/src/routes/server-side-rendered/+page.svelte similarity index 79% rename from packages/app-sveltekit/src/routes/mpa/+page.svelte rename to packages/app-sveltekit/src/routes/server-side-rendered/+page.svelte index 01a2f34b..1b853078 100644 --- a/packages/app-sveltekit/src/routes/mpa/+page.svelte +++ b/packages/app-sveltekit/src/routes/server-side-rendered/+page.svelte @@ -9,7 +9,7 @@ {/each} diff --git a/packages/app-sveltekit/src/routes/mpa/+page.ts b/packages/app-sveltekit/src/routes/server-side-rendered/+page.ts similarity index 100% rename from packages/app-sveltekit/src/routes/mpa/+page.ts rename to packages/app-sveltekit/src/routes/server-side-rendered/+page.ts diff --git a/packages/app-sveltekit/src/routes/mpa/[id]/+page.server.ts b/packages/app-sveltekit/src/routes/server-side-rendered/[id]/+page.server.ts similarity index 100% rename from packages/app-sveltekit/src/routes/mpa/[id]/+page.server.ts rename to packages/app-sveltekit/src/routes/server-side-rendered/[id]/+page.server.ts diff --git a/packages/app-sveltekit/src/routes/mpa/[id]/+page.svelte b/packages/app-sveltekit/src/routes/server-side-rendered/[id]/+page.svelte similarity index 100% rename from packages/app-sveltekit/src/routes/mpa/[id]/+page.svelte rename to packages/app-sveltekit/src/routes/server-side-rendered/[id]/+page.svelte diff --git a/packages/app-sveltekit/src/routes/mpa/[id]/+page.ts b/packages/app-sveltekit/src/routes/server-side-rendered/[id]/+page.ts similarity index 100% rename from packages/app-sveltekit/src/routes/mpa/[id]/+page.ts rename to packages/app-sveltekit/src/routes/server-side-rendered/[id]/+page.ts diff --git a/packages/app-sveltekit/stats/2.49.4.json b/packages/app-sveltekit/stats/2.49.4.json index c953d1f9..8c9f920b 100644 --- a/packages/app-sveltekit/stats/2.49.4.json +++ b/packages/app-sveltekit/stats/2.49.4.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "2.49.4", - "ssrOpsPerSec": 437, - "ssrAvgLatencyMs": 2.337, - "ssrMedianLatencyMs": 2.221, - "ssrSamples": 4279, - "ssrBodySizeKb": 183.55, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 72.4, - "mpaFCPMs": 72.44, - "mpaINPMs": 0.45, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 106.6, "fcpMs": 106.59, "inpMs": 13.96, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 437, + "avgLatencyMs": 2.337, + "medianLatencyMs": 2.221, + "samples": 4279, + "bodySizeKb": 183.55, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 72.4, + "fcpMs": 72.44, + "inpMs": 0.45, + "runs": 5 } } diff --git a/packages/app-tanstack-start-react/ci-stats.json b/packages/app-tanstack-start-react/ci-stats.json index 351c5144..7eb45030 100644 --- a/packages/app-tanstack-start-react/ci-stats.json +++ b/packages/app-tanstack-start-react/ci-stats.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "1.145.3", - "ssrOpsPerSec": 312, - "ssrAvgLatencyMs": 3.234, - "ssrMedianLatencyMs": 3.163, - "ssrSamples": 3092, - "ssrBodySizeKb": 193.53, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 81.2, - "mpaFCPMs": 81.16, - "mpaINPMs": 3.36, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 144.6, "fcpMs": 144.81, "inpMs": 26.14, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 312, + "avgLatencyMs": 3.234, + "medianLatencyMs": 3.163, + "samples": 3092, + "bodySizeKb": 193.53, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 81.2, + "fcpMs": 81.16, + "inpMs": 3.36, + "runs": 5 } } diff --git a/packages/app-tanstack-start-react/src/routeTree.gen.ts b/packages/app-tanstack-start-react/src/routeTree.gen.ts index 794e5d2c..dacbcf41 100644 --- a/packages/app-tanstack-start-react/src/routeTree.gen.ts +++ b/packages/app-tanstack-start-react/src/routeTree.gen.ts @@ -9,20 +9,20 @@ // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. import { Route as rootRouteImport } from './routes/__root' -import { Route as SpaRouteImport } from './routes/spa' -import { Route as MpaRouteImport } from './routes/mpa' +import { Route as ServerSideRenderedRouteImport } from './routes/server-side-rendered' +import { Route as ClientSideRenderedRouteImport } from './routes/client-side-rendered' import { Route as IndexRouteImport } from './routes/index' -import { Route as SpaIdRouteImport } from './routes/spa_.$id' -import { Route as MpaIdRouteImport } from './routes/mpa_.$id' +import { Route as ServerSideRenderedIdRouteImport } from './routes/server-side-rendered_.$id' +import { Route as ClientSideRenderedIdRouteImport } from './routes/client-side-rendered_.$id' -const SpaRoute = SpaRouteImport.update({ - id: '/spa', - path: '/spa', +const ServerSideRenderedRoute = ServerSideRenderedRouteImport.update({ + id: '/server-side-rendered', + path: '/server-side-rendered', getParentRoute: () => rootRouteImport, } as any) -const MpaRoute = MpaRouteImport.update({ - id: '/mpa', - path: '/mpa', +const ClientSideRenderedRoute = ClientSideRenderedRouteImport.update({ + id: '/client-side-rendered', + path: '/client-side-rendered', getParentRoute: () => rootRouteImport, } as any) const IndexRoute = IndexRouteImport.update({ @@ -30,69 +30,85 @@ const IndexRoute = IndexRouteImport.update({ path: '/', getParentRoute: () => rootRouteImport, } as any) -const SpaIdRoute = SpaIdRouteImport.update({ - id: '/spa_/$id', - path: '/spa/$id', +const ServerSideRenderedIdRoute = ServerSideRenderedIdRouteImport.update({ + id: '/server-side-rendered_/$id', + path: '/server-side-rendered/$id', getParentRoute: () => rootRouteImport, } as any) -const MpaIdRoute = MpaIdRouteImport.update({ - id: '/mpa_/$id', - path: '/mpa/$id', +const ClientSideRenderedIdRoute = ClientSideRenderedIdRouteImport.update({ + id: '/client-side-rendered_/$id', + path: '/client-side-rendered/$id', getParentRoute: () => rootRouteImport, } as any) export interface FileRoutesByFullPath { '/': typeof IndexRoute - '/mpa': typeof MpaRoute - '/spa': typeof SpaRoute - '/mpa/$id': typeof MpaIdRoute - '/spa/$id': typeof SpaIdRoute + '/client-side-rendered': typeof ClientSideRenderedRoute + '/server-side-rendered': typeof ServerSideRenderedRoute + '/client-side-rendered/$id': typeof ClientSideRenderedIdRoute + '/server-side-rendered/$id': typeof ServerSideRenderedIdRoute } export interface FileRoutesByTo { '/': typeof IndexRoute - '/mpa': typeof MpaRoute - '/spa': typeof SpaRoute - '/mpa/$id': typeof MpaIdRoute - '/spa/$id': typeof SpaIdRoute + '/client-side-rendered': typeof ClientSideRenderedRoute + '/server-side-rendered': typeof ServerSideRenderedRoute + '/client-side-rendered/$id': typeof ClientSideRenderedIdRoute + '/server-side-rendered/$id': typeof ServerSideRenderedIdRoute } export interface FileRoutesById { __root__: typeof rootRouteImport '/': typeof IndexRoute - '/mpa': typeof MpaRoute - '/spa': typeof SpaRoute - '/mpa_/$id': typeof MpaIdRoute - '/spa_/$id': typeof SpaIdRoute + '/client-side-rendered': typeof ClientSideRenderedRoute + '/server-side-rendered': typeof ServerSideRenderedRoute + '/client-side-rendered_/$id': typeof ClientSideRenderedIdRoute + '/server-side-rendered_/$id': typeof ServerSideRenderedIdRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: '/' | '/mpa' | '/spa' | '/mpa/$id' | '/spa/$id' + fullPaths: + | '/' + | '/client-side-rendered' + | '/server-side-rendered' + | '/client-side-rendered/$id' + | '/server-side-rendered/$id' fileRoutesByTo: FileRoutesByTo - to: '/' | '/mpa' | '/spa' | '/mpa/$id' | '/spa/$id' - id: '__root__' | '/' | '/mpa' | '/spa' | '/mpa_/$id' | '/spa_/$id' + to: + | '/' + | '/client-side-rendered' + | '/server-side-rendered' + | '/client-side-rendered/$id' + | '/server-side-rendered/$id' + id: + | '__root__' + | '/' + | '/client-side-rendered' + | '/server-side-rendered' + | '/client-side-rendered_/$id' + | '/server-side-rendered_/$id' fileRoutesById: FileRoutesById } export interface RootRouteChildren { IndexRoute: typeof IndexRoute - MpaRoute: typeof MpaRoute - SpaRoute: typeof SpaRoute - MpaIdRoute: typeof MpaIdRoute - SpaIdRoute: typeof SpaIdRoute + ClientSideRenderedRoute: typeof ClientSideRenderedRoute + ServerSideRenderedRoute: typeof ServerSideRenderedRoute + ClientSideRenderedIdRoute: typeof ClientSideRenderedIdRoute + ServerSideRenderedIdRoute: typeof ServerSideRenderedIdRoute } declare module '@tanstack/react-router' { interface FileRoutesByPath { - '/spa': { - id: '/spa' - path: '/spa' - fullPath: '/spa' - preLoaderRoute: typeof SpaRouteImport + '/server-side-rendered': { + id: '/server-side-rendered' + path: '/server-side-rendered' + fullPath: '/server-side-rendered' + preLoaderRoute: typeof ServerSideRenderedRouteImport parentRoute: typeof rootRouteImport } - '/mpa': { - id: '/mpa' - path: '/mpa' - fullPath: '/mpa' - preLoaderRoute: typeof MpaRouteImport + '/client-side-rendered': { + id: '/client-side-rendered' + path: '/client-side-rendered' + fullPath: '/client-side-rendered' + preLoaderRoute: typeof ClientSideRenderedRouteImport parentRoute: typeof rootRouteImport } '/': { @@ -102,18 +118,18 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof IndexRouteImport parentRoute: typeof rootRouteImport } - '/spa_/$id': { - id: '/spa_/$id' - path: '/spa/$id' - fullPath: '/spa/$id' - preLoaderRoute: typeof SpaIdRouteImport + '/server-side-rendered_/$id': { + id: '/server-side-rendered_/$id' + path: '/server-side-rendered/$id' + fullPath: '/server-side-rendered/$id' + preLoaderRoute: typeof ServerSideRenderedIdRouteImport parentRoute: typeof rootRouteImport } - '/mpa_/$id': { - id: '/mpa_/$id' - path: '/mpa/$id' - fullPath: '/mpa/$id' - preLoaderRoute: typeof MpaIdRouteImport + '/client-side-rendered_/$id': { + id: '/client-side-rendered_/$id' + path: '/client-side-rendered/$id' + fullPath: '/client-side-rendered/$id' + preLoaderRoute: typeof ClientSideRenderedIdRouteImport parentRoute: typeof rootRouteImport } } @@ -121,10 +137,10 @@ declare module '@tanstack/react-router' { const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, - MpaRoute: MpaRoute, - SpaRoute: SpaRoute, - MpaIdRoute: MpaIdRoute, - SpaIdRoute: SpaIdRoute, + ClientSideRenderedRoute: ClientSideRenderedRoute, + ServerSideRenderedRoute: ServerSideRenderedRoute, + ClientSideRenderedIdRoute: ClientSideRenderedIdRoute, + ServerSideRenderedIdRoute: ServerSideRenderedIdRoute, } export const routeTree = rootRouteImport ._addFileChildren(rootRouteChildren) diff --git a/packages/app-tanstack-start-react/src/routes/spa.tsx b/packages/app-tanstack-start-react/src/routes/client-side-rendered.tsx similarity index 75% rename from packages/app-tanstack-start-react/src/routes/spa.tsx rename to packages/app-tanstack-start-react/src/routes/client-side-rendered.tsx index 22f024e0..de6ff888 100644 --- a/packages/app-tanstack-start-react/src/routes/spa.tsx +++ b/packages/app-tanstack-start-react/src/routes/client-side-rendered.tsx @@ -1,8 +1,8 @@ import { createFileRoute, Link } from '@tanstack/react-router' import { useState } from 'react' -export const Route = createFileRoute('/spa')({ - component: SpaPage, +export const Route = createFileRoute('/client-side-rendered')({ + component: ClientSideRenderedPage, }) type Entry = { id: string; name: string } @@ -14,7 +14,7 @@ function generateData(): Entry[] { })) } -function SpaPage() { +function ClientSideRenderedPage() { const [entries] = useState(generateData) return ( @@ -25,7 +25,7 @@ function SpaPage() { diff --git a/packages/app-tanstack-start-react/src/routes/client-side-rendered_.$id.tsx b/packages/app-tanstack-start-react/src/routes/client-side-rendered_.$id.tsx new file mode 100644 index 00000000..0a5e0167 --- /dev/null +++ b/packages/app-tanstack-start-react/src/routes/client-side-rendered_.$id.tsx @@ -0,0 +1,11 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/client-side-rendered_/$id')({ + component: ClientSideRenderedDetailPage, +}) + +function ClientSideRenderedDetailPage() { + const { id } = Route.useParams() + + return

{id}

+} diff --git a/packages/app-tanstack-start-react/src/routes/mpa_.$id.tsx b/packages/app-tanstack-start-react/src/routes/mpa_.$id.tsx deleted file mode 100644 index c162c399..00000000 --- a/packages/app-tanstack-start-react/src/routes/mpa_.$id.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { createFileRoute } from '@tanstack/react-router' - -export const Route = createFileRoute('/mpa_/$id')({ - component: MpaDetailPage, -}) - -function MpaDetailPage() { - const { id } = Route.useParams() - - return

{id}

-} diff --git a/packages/app-tanstack-start-react/src/routes/mpa.tsx b/packages/app-tanstack-start-react/src/routes/server-side-rendered.tsx similarity index 70% rename from packages/app-tanstack-start-react/src/routes/mpa.tsx rename to packages/app-tanstack-start-react/src/routes/server-side-rendered.tsx index 0dc6ec4e..515c3953 100644 --- a/packages/app-tanstack-start-react/src/routes/mpa.tsx +++ b/packages/app-tanstack-start-react/src/routes/server-side-rendered.tsx @@ -1,12 +1,12 @@ import { createFileRoute, Link } from '@tanstack/react-router' import { testData } from '../../../testdata/src/ssr' -export const Route = createFileRoute('/mpa')({ - component: MpaPage, +export const Route = createFileRoute('/server-side-rendered')({ + component: ServerSideRenderedPage, loader: async () => await testData(), }) -function MpaPage() { +function ServerSideRenderedPage() { const data = Route.useLoaderData() return ( @@ -17,7 +17,7 @@ function MpaPage() { diff --git a/packages/app-tanstack-start-react/src/routes/server-side-rendered_.$id.tsx b/packages/app-tanstack-start-react/src/routes/server-side-rendered_.$id.tsx new file mode 100644 index 00000000..e56e9c4d --- /dev/null +++ b/packages/app-tanstack-start-react/src/routes/server-side-rendered_.$id.tsx @@ -0,0 +1,11 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/server-side-rendered_/$id')({ + component: ServerSideRenderedDetailPage, +}) + +function ServerSideRenderedDetailPage() { + const { id } = Route.useParams() + + return

{id}

+} diff --git a/packages/app-tanstack-start-react/src/routes/spa_.$id.tsx b/packages/app-tanstack-start-react/src/routes/spa_.$id.tsx deleted file mode 100644 index 766faf36..00000000 --- a/packages/app-tanstack-start-react/src/routes/spa_.$id.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { createFileRoute } from '@tanstack/react-router' - -export const Route = createFileRoute('/spa_/$id')({ - component: SpaDetailPage, -}) - -function SpaDetailPage() { - const { id } = Route.useParams() - - return

{id}

-} diff --git a/packages/app-tanstack-start-react/stats/1.145.3.json b/packages/app-tanstack-start-react/stats/1.145.3.json index 351c5144..7eb45030 100644 --- a/packages/app-tanstack-start-react/stats/1.145.3.json +++ b/packages/app-tanstack-start-react/stats/1.145.3.json @@ -2,20 +2,24 @@ "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "1.145.3", - "ssrOpsPerSec": 312, - "ssrAvgLatencyMs": 3.234, - "ssrMedianLatencyMs": 3.163, - "ssrSamples": 3092, - "ssrBodySizeKb": 193.53, - "ssrDuplicationFactor": 2, - "mpaFirstPaintMs": 81.2, - "mpaFCPMs": 81.16, - "mpaINPMs": 3.36, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 144.6, "fcpMs": 144.81, "inpMs": 26.14, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 312, + "avgLatencyMs": 3.234, + "medianLatencyMs": 3.163, + "samples": 3092, + "bodySizeKb": 193.53, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 81.2, + "fcpMs": 81.16, + "inpMs": 3.36, + "runs": 5 } } diff --git a/packages/app-tanstack-start-react/vite.config.ts b/packages/app-tanstack-start-react/vite.config.ts index 5d64b86c..64afa3e4 100644 --- a/packages/app-tanstack-start-react/vite.config.ts +++ b/packages/app-tanstack-start-react/vite.config.ts @@ -3,15 +3,15 @@ import viteReact from '@vitejs/plugin-react' import { nitro } from 'nitro/vite' import { defineConfig } from 'vite' -const isSpa = process.env.BUILD_MODE === 'spa' +const isClientSideRendered = process.env.BUILD_MODE === 'spa' export default defineConfig({ preview: { host: '127.0.0.1', }, plugins: [ - ...(isSpa ? [] : [nitro({ preset: 'node-middleware' })]), - tanstackStart({ spa: { enabled: isSpa } }), + ...(isClientSideRendered ? [] : [nitro({ preset: 'node-middleware' })]), + tanstackStart({ spa: { enabled: isClientSideRendered } }), viteReact(), ], }) diff --git a/packages/docs/src/components/ClientSideRenderedStatsMethodologyNotes.astro b/packages/docs/src/components/ClientSideRenderedStatsMethodologyNotes.astro index 4eaccdaf..7fe10005 100644 --- a/packages/docs/src/components/ClientSideRenderedStatsMethodologyNotes.astro +++ b/packages/docs/src/components/ClientSideRenderedStatsMethodologyNotes.astro @@ -18,11 +18,12 @@ import MethodologyNotes from '../components/MethodologyNotes.astro'
  • 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 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 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. + > in its config. All other frameworks (Nuxt, SvelteKit, SolidStart, Astro) disable + SSR per-route without a separate build.
  • diff --git a/packages/docs/src/components/MPACharts.astro b/packages/docs/src/components/MPACharts.astro deleted file mode 100644 index fd43db18..00000000 --- a/packages/docs/src/components/MPACharts.astro +++ /dev/null @@ -1,18 +0,0 @@ ---- -import ChartTabs from './ChartTabs.astro' -import MPAFPChart from './MPAFPChart.astro' -import MPAFCPChart from './MPAFCPChart.astro' -import MPAINPChart from './MPAINPChart.astro' ---- - - - - - - diff --git a/packages/docs/src/components/SSRBodySizeChart.astro b/packages/docs/src/components/SSRBodySizeChart.astro deleted file mode 100644 index c8f99794..00000000 --- a/packages/docs/src/components/SSRBodySizeChart.astro +++ /dev/null @@ -1,16 +0,0 @@ ---- -import { ssrStats } from '../lib/collections' -import ComparisonBarChart from './ComparisonBarChart.astro' - -const data = ssrStats - .filter((f) => f?.name != null && Number.isFinite(f.ssrBodySizeKb)) - .map((f) => ({ name: f.name, value: f.ssrBodySizeKb, focused: f.isFocused })) - .sort((a, b) => a.value - b.value || a.name.localeCompare(b.name)) ---- - - diff --git a/packages/docs/src/components/SSRCharts.astro b/packages/docs/src/components/SSRCharts.astro deleted file mode 100644 index c26c14b4..00000000 --- a/packages/docs/src/components/SSRCharts.astro +++ /dev/null @@ -1,18 +0,0 @@ ---- -import ChartTabs from './ChartTabs.astro' -import SSRBodySizeChart from './SSRBodySizeChart.astro' -import SSRLatencyChart from './SSRLatencyChart.astro' -import SSROpsChart from './SSROpsChart.astro' ---- - - - - - - diff --git a/packages/docs/src/components/SSROpsChart.astro b/packages/docs/src/components/SSROpsChart.astro deleted file mode 100644 index 69448026..00000000 --- a/packages/docs/src/components/SSROpsChart.astro +++ /dev/null @@ -1,16 +0,0 @@ ---- -import { ssrStats } from '../lib/collections' -import ComparisonBarChart from './ComparisonBarChart.astro' - -const data = ssrStats - .filter((f) => f?.name != null && Number.isFinite(f.ssrOpsPerSec)) - .map((f) => ({ name: f.name, value: f.ssrOpsPerSec, focused: f.isFocused })) - .sort((a, b) => b.value - a.value || a.name.localeCompare(b.name)) ---- - - diff --git a/packages/docs/src/components/SSRRequestThroughputBodySizeChart.astro b/packages/docs/src/components/SSRRequestThroughputBodySizeChart.astro new file mode 100644 index 00000000..66184a0d --- /dev/null +++ b/packages/docs/src/components/SSRRequestThroughputBodySizeChart.astro @@ -0,0 +1,20 @@ +--- +import { ssrRequestThroughputStats } from '../lib/collections' +import ComparisonBarChart from './ComparisonBarChart.astro' + +const data = ssrRequestThroughputStats + .filter((f) => Number.isFinite(f.ssrRequestThroughputTests.bodySizeKb)) + .map((f) => ({ + name: f.name, + value: f.ssrRequestThroughputTests.bodySizeKb, + focused: f.isFocused, + })) + .sort((a, b) => a.value - b.value || a.name.localeCompare(b.name)) +--- + + diff --git a/packages/docs/src/components/SSRRequestThroughputCharts.astro b/packages/docs/src/components/SSRRequestThroughputCharts.astro new file mode 100644 index 00000000..dcbad720 --- /dev/null +++ b/packages/docs/src/components/SSRRequestThroughputCharts.astro @@ -0,0 +1,18 @@ +--- +import ChartTabs from './ChartTabs.astro' +import SSRRequestThroughputBodySizeChart from './SSRRequestThroughputBodySizeChart.astro' +import SSRRequestThroughputLatencyChart from './SSRRequestThroughputLatencyChart.astro' +import SSRRequestThroughputOpsChart from './SSRRequestThroughputOpsChart.astro' +--- + + + + + + diff --git a/packages/docs/src/components/SSRLatencyChart.astro b/packages/docs/src/components/SSRRequestThroughputLatencyChart.astro similarity index 70% rename from packages/docs/src/components/SSRLatencyChart.astro rename to packages/docs/src/components/SSRRequestThroughputLatencyChart.astro index 91ddb38d..821f0293 100644 --- a/packages/docs/src/components/SSRLatencyChart.astro +++ b/packages/docs/src/components/SSRRequestThroughputLatencyChart.astro @@ -1,11 +1,11 @@ --- -import { ssrStats } from '../lib/collections' +import { ssrRequestThroughputStats } from '../lib/collections' import ComparisonBarChart from './ComparisonBarChart.astro' -const data = ssrStats +const data = ssrRequestThroughputStats .map((f) => ({ name: f.name, - value: f.ssrMedianLatencyMs, + value: f.ssrRequestThroughputTests.medianLatencyMs, focused: f.isFocused, })) .filter((f) => f?.name != null && Number.isFinite(f.value)) diff --git a/packages/docs/src/components/SSRRequestThroughputOpsChart.astro b/packages/docs/src/components/SSRRequestThroughputOpsChart.astro new file mode 100644 index 00000000..f8de8902 --- /dev/null +++ b/packages/docs/src/components/SSRRequestThroughputOpsChart.astro @@ -0,0 +1,20 @@ +--- +import { ssrRequestThroughputStats } from '../lib/collections' +import ComparisonBarChart from './ComparisonBarChart.astro' + +const data = ssrRequestThroughputStats + .filter((f) => Number.isFinite(f.ssrRequestThroughputTests.opsPerSec)) + .map((f) => ({ + name: f.name, + value: f.ssrRequestThroughputTests.opsPerSec, + focused: f.isFocused, + })) + .sort((a, b) => b.value - a.value || a.name.localeCompare(b.name)) +--- + + diff --git a/packages/docs/src/components/SSRStatsMethodologyNotes.astro b/packages/docs/src/components/SSRRequestThroughputStatsMethodologyNotes.astro similarity index 84% rename from packages/docs/src/components/SSRStatsMethodologyNotes.astro rename to packages/docs/src/components/SSRRequestThroughputStatsMethodologyNotes.astro index 74392e36..566f14a3 100644 --- a/packages/docs/src/components/SSRStatsMethodologyNotes.astro +++ b/packages/docs/src/components/SSRRequestThroughputStatsMethodologyNotes.astro @@ -28,10 +28,9 @@ import MethodologyNotes from '../components/MethodologyNotes.astro'
  • 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 + model than traditional server-rendered React. To keep the comparison fair, + Next.js uses "use client" to opt out of RSC and use traditional server + rendering + hydration like most of the other frameworks
  • Inspired by ) => + row.package !== 'app-baseline-html' + ? `/framework/${getFrameworkSlug(row.package as string)}` + : null, + }, + { key: 'opsPerSec', header: 'Ops/sec' }, + { key: 'medianLatencyMs', header: 'Median Latency' }, + { key: 'bodySizeKb', header: 'Body Size' }, + { key: 'duplicationFactor', header: 'Duplication' }, +] + +const tableData = ssrRequestThroughputStats.map((f) => ({ + name: f.name, + package: f.package, + isFocused: f.package === 'app-baseline-html' ? true : f.isFocused, + opsPerSec: f.ssrRequestThroughputTests.opsPerSec.toLocaleString(), + medianLatencyMs: `${f.ssrRequestThroughputTests.medianLatencyMs}ms`, + bodySizeKb: `${f.ssrRequestThroughputTests.bodySizeKb}kb`, + duplicationFactor: `${f.ssrRequestThroughputTests.duplicationFactor}x`, +})) +--- + + diff --git a/packages/docs/src/components/SSRStatsTable.astro b/packages/docs/src/components/SSRStatsTable.astro deleted file mode 100644 index 0d3dbd7a..00000000 --- a/packages/docs/src/components/SSRStatsTable.astro +++ /dev/null @@ -1,37 +0,0 @@ ---- -import { ssrStats } from '../lib/collections' -import { getFrameworkSlug } from '../lib/utils' -import StatsTable from './StatsTable.astro' - -const columns = [ - { - key: 'name', - header: 'Framework', - nameCell: true, - href: (row: Record) => - row.package !== 'app-baseline-html' - ? `/framework/${getFrameworkSlug(row.package as string)}` - : null, - }, - { key: 'ssrOpsPerSec', header: 'Ops/sec' }, - { key: 'ssrLatencyMs', header: 'Median Latency' }, - { key: 'ssrBodySizeKb', header: 'Body Size' }, - { key: 'ssrDuplicationFactor', header: 'Duplication' }, -] - -const tableData = ssrStats.map((f) => ({ - name: f.name, - package: f.package, - isFocused: f.package === 'app-baseline-html' ? true : f.isFocused, - ssrOpsPerSec: f.ssrOpsPerSec?.toLocaleString() ?? '', - ssrLatencyMs: `${f.ssrMedianLatencyMs}ms`, - ssrBodySizeKb: `${f.ssrBodySizeKb}kb`, - ssrDuplicationFactor: `${f.ssrDuplicationFactor}x`, -})) ---- - - diff --git a/packages/docs/src/components/ServerSideRenderedCharts.astro b/packages/docs/src/components/ServerSideRenderedCharts.astro new file mode 100644 index 00000000..9671e248 --- /dev/null +++ b/packages/docs/src/components/ServerSideRenderedCharts.astro @@ -0,0 +1,18 @@ +--- +import ChartTabs from './ChartTabs.astro' +import ServerSideRenderedFPChart from './ServerSideRenderedFPChart.astro' +import ServerSideRenderedFCPChart from './ServerSideRenderedFCPChart.astro' +import ServerSideRenderedINPChart from './ServerSideRenderedINPChart.astro' +--- + + + + + + diff --git a/packages/docs/src/components/MPAFCPChart.astro b/packages/docs/src/components/ServerSideRenderedFCPChart.astro similarity index 67% rename from packages/docs/src/components/MPAFCPChart.astro rename to packages/docs/src/components/ServerSideRenderedFCPChart.astro index 8fa6797f..c2ea1263 100644 --- a/packages/docs/src/components/MPAFCPChart.astro +++ b/packages/docs/src/components/ServerSideRenderedFCPChart.astro @@ -1,8 +1,8 @@ --- -import { chartMPAFCPData } from '../lib/collections' +import { chartServerSideRenderedFCPData } from '../lib/collections' import ComparisonBarChart from './ComparisonBarChart.astro' -const data = [...chartMPAFCPData].sort( +const data = [...chartServerSideRenderedFCPData].sort( (a, b) => a.value - b.value || a.name.localeCompare(b.name), ) --- diff --git a/packages/docs/src/components/MPAFPChart.astro b/packages/docs/src/components/ServerSideRenderedFPChart.astro similarity index 67% rename from packages/docs/src/components/MPAFPChart.astro rename to packages/docs/src/components/ServerSideRenderedFPChart.astro index 0417be47..1017faed 100644 --- a/packages/docs/src/components/MPAFPChart.astro +++ b/packages/docs/src/components/ServerSideRenderedFPChart.astro @@ -1,8 +1,8 @@ --- -import { chartMPAFPData } from '../lib/collections' +import { chartServerSideRenderedFPData } from '../lib/collections' import ComparisonBarChart from './ComparisonBarChart.astro' -const data = [...chartMPAFPData].sort( +const data = [...chartServerSideRenderedFPData].sort( (a, b) => a.value - b.value || a.name.localeCompare(b.name), ) --- diff --git a/packages/docs/src/components/MPAINPChart.astro b/packages/docs/src/components/ServerSideRenderedINPChart.astro similarity index 67% rename from packages/docs/src/components/MPAINPChart.astro rename to packages/docs/src/components/ServerSideRenderedINPChart.astro index ed38cb1e..d95f24b5 100644 --- a/packages/docs/src/components/MPAINPChart.astro +++ b/packages/docs/src/components/ServerSideRenderedINPChart.astro @@ -1,8 +1,8 @@ --- -import { chartMPAINPData } from '../lib/collections' +import { chartServerSideRenderedINPData } from '../lib/collections' import ComparisonBarChart from './ComparisonBarChart.astro' -const data = [...chartMPAINPData].sort( +const data = [...chartServerSideRenderedINPData].sort( (a, b) => a.value - b.value || a.name.localeCompare(b.name), ) --- diff --git a/packages/docs/src/components/MPAStatsMethodologyNotes.astro b/packages/docs/src/components/ServerSideRenderedStatsMethodologyNotes.astro similarity index 54% rename from packages/docs/src/components/MPAStatsMethodologyNotes.astro rename to packages/docs/src/components/ServerSideRenderedStatsMethodologyNotes.astro index 4eaccdaf..c2d62fb0 100644 --- a/packages/docs/src/components/MPAStatsMethodologyNotes.astro +++ b/packages/docs/src/components/ServerSideRenderedStatsMethodologyNotes.astro @@ -17,12 +17,7 @@ import MethodologyNotes from '../components/MethodologyNotes.astro'
  • 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. + The measured route is /server-side-rendered, and detail + navigation uses /server-side-rendered/:id.
  • diff --git a/packages/docs/src/components/MPAStatsTable.astro b/packages/docs/src/components/ServerSideRenderedStatsTable.astro similarity index 59% rename from packages/docs/src/components/MPAStatsTable.astro rename to packages/docs/src/components/ServerSideRenderedStatsTable.astro index 3b7c7b15..146d1255 100644 --- a/packages/docs/src/components/MPAStatsTable.astro +++ b/packages/docs/src/components/ServerSideRenderedStatsTable.astro @@ -1,5 +1,5 @@ --- -import { mpaStats } from '../lib/collections' +import { serverSideRenderedStats } from '../lib/collections' import { getFrameworkSlug } from '../lib/utils' import StatsTable from './StatsTable.astro' @@ -13,16 +13,16 @@ const columns = [ ? `/framework/${getFrameworkSlug(row.package as string)}` : null, }, - { key: 'mpaFirstPaintMs', header: 'First Paint' }, - { key: 'mpaFCPMs', header: 'FCP' }, - { key: 'mpaINPMs', header: 'INP' }, + { key: 'firstPaintMs', header: 'First Paint' }, + { key: 'fcpMs', header: 'FCP' }, + { key: 'inpMs', header: 'INP' }, ] -const tableData = mpaStats +const tableData = serverSideRenderedStats --- diff --git a/packages/docs/src/content.config.ts b/packages/docs/src/content.config.ts index 512cd0ed..8647b278 100644 --- a/packages/docs/src/content.config.ts +++ b/packages/docs/src/content.config.ts @@ -51,12 +51,14 @@ const runtimeCollection = defineCollection({ package: z.string(), isFocused: z.boolean(), order: z.number(), - ssrOpsPerSec: z.number(), - ssrAvgLatencyMs: z.number(), - ssrMedianLatencyMs: z.number(), - ssrSamples: z.number(), - ssrBodySizeKb: z.number(), - ssrDuplicationFactor: z.number(), + ssrRequestThroughputTests: z.object({ + opsPerSec: z.number(), + avgLatencyMs: z.number(), + medianLatencyMs: z.number(), + samples: z.number(), + bodySizeKb: z.number(), + duplicationFactor: z.number(), + }), // Client-side rendered paint + interaction metrics clientSideRenderedTests: z .object({ @@ -67,11 +69,15 @@ const runtimeCollection = defineCollection({ }) .optional(), - // MPA paint + interaction metrics - mpaFirstPaintMs: z.number().optional(), - mpaFCPMs: z.number().optional(), - mpaINPMs: z.number().optional(), - mpaRuns: z.number().optional(), + // Server-side rendered route paint + interaction metrics + serverSideRenderedTests: z + .object({ + firstPaintMs: z.number(), + fcpMs: z.number(), + inpMs: z.number(), + runs: z.number(), + }) + .optional(), }), }) diff --git a/packages/docs/src/content/runtime/app-astro.json b/packages/docs/src/content/runtime/app-astro.json index 03e6d3fb..8da57f1a 100644 --- a/packages/docs/src/content/runtime/app-astro.json +++ b/packages/docs/src/content/runtime/app-astro.json @@ -2,25 +2,29 @@ "name": "Astro", "package": "app-astro", "isFocused": true, - "type": "ssr-app", - "ssrOpsPerSec": 570, - "ssrAvgLatencyMs": 1.769, - "ssrMedianLatencyMs": 1.745, - "ssrSamples": 5653, - "ssrBodySizeKb": 99.86, - "ssrDuplicationFactor": 1, + "type": "runtime-app", "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "5.16.15", "order": 1, - "mpaFirstPaintMs": 68.8, - "mpaFCPMs": 68.87, - "mpaINPMs": 3.41, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 92.4, "fcpMs": 92.3, "inpMs": 6.29, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 570, + "avgLatencyMs": 1.769, + "medianLatencyMs": 1.745, + "samples": 5653, + "bodySizeKb": 99.86, + "duplicationFactor": 1 + }, + "serverSideRenderedTests": { + "firstPaintMs": 68.8, + "fcpMs": 68.87, + "inpMs": 3.41, + "runs": 5 } } diff --git a/packages/docs/src/content/runtime/app-baseline-html.json b/packages/docs/src/content/runtime/app-baseline-html.json index 1102fb75..30c1c3a2 100644 --- a/packages/docs/src/content/runtime/app-baseline-html.json +++ b/packages/docs/src/content/runtime/app-baseline-html.json @@ -1,15 +1,17 @@ { "name": "Baseline HTML", "package": "app-baseline-html", - "type": "ssr-app", + "type": "runtime-app", "isFocused": false, - "ssrOpsPerSec": 848, - "ssrAvgLatencyMs": 1.202, - "ssrMedianLatencyMs": 1.202, - "ssrSamples": 8319, - "ssrBodySizeKb": 96.81, - "ssrDuplicationFactor": 1, "order": 0, "timingMeasuredAt": "2026-06-21T10:18:43.575Z", - "runner": "ubuntu-latest" + "runner": "ubuntu-latest", + "ssrRequestThroughputTests": { + "opsPerSec": 848, + "avgLatencyMs": 1.202, + "medianLatencyMs": 1.202, + "samples": 8319, + "bodySizeKb": 96.81, + "duplicationFactor": 1 + } } diff --git a/packages/docs/src/content/runtime/app-mastro.json b/packages/docs/src/content/runtime/app-mastro.json index dc3869d0..7d2123d1 100644 --- a/packages/docs/src/content/runtime/app-mastro.json +++ b/packages/docs/src/content/runtime/app-mastro.json @@ -1,15 +1,17 @@ { "name": "Mastro", "package": "app-mastro", - "type": "ssr-app", + "type": "runtime-app", "isFocused": false, "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", - "ssrOpsPerSec": 502, - "ssrAvgLatencyMs": 2.013, - "ssrMedianLatencyMs": 1.986, - "ssrSamples": 4967, - "ssrBodySizeKb": 181.95, - "ssrDuplicationFactor": 1, - "order": 2 + "order": 2, + "ssrRequestThroughputTests": { + "opsPerSec": 502, + "avgLatencyMs": 2.013, + "medianLatencyMs": 1.986, + "samples": 4967, + "bodySizeKb": 181.95, + "duplicationFactor": 1 + } } diff --git a/packages/docs/src/content/runtime/app-next-js.json b/packages/docs/src/content/runtime/app-next-js.json index 512fbb86..9356dcd1 100644 --- a/packages/docs/src/content/runtime/app-next-js.json +++ b/packages/docs/src/content/runtime/app-next-js.json @@ -2,25 +2,29 @@ "name": "Next.js", "package": "app-next-js", "isFocused": true, - "type": "ssr-app", + "type": "runtime-app", "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "16.1.1", - "ssrOpsPerSec": 215, - "ssrAvgLatencyMs": 4.78, - "ssrMedianLatencyMs": 4.812, - "ssrSamples": 2092, - "ssrBodySizeKb": 199.11, - "ssrDuplicationFactor": 2, "order": 3, - "mpaFirstPaintMs": 124.2, - "mpaFCPMs": 124.06, - "mpaINPMs": 0, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 348.6, "fcpMs": 348.55, "inpMs": 16.28, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 215, + "avgLatencyMs": 4.78, + "medianLatencyMs": 4.812, + "samples": 2092, + "bodySizeKb": 199.11, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 124.2, + "fcpMs": 124.06, + "inpMs": 0, + "runs": 5 } } diff --git a/packages/docs/src/content/runtime/app-nuxt.json b/packages/docs/src/content/runtime/app-nuxt.json index f048a601..d106dc3f 100644 --- a/packages/docs/src/content/runtime/app-nuxt.json +++ b/packages/docs/src/content/runtime/app-nuxt.json @@ -2,25 +2,29 @@ "name": "Nuxt", "package": "app-nuxt", "isFocused": true, - "type": "ssr-app", - "ssrOpsPerSec": 384, - "ssrAvgLatencyMs": 2.664, - "ssrMedianLatencyMs": 2.544, - "ssrSamples": 3755, - "ssrBodySizeKb": 201.26, - "ssrDuplicationFactor": 2, + "type": "runtime-app", "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "4.2.2", "order": 4, - "mpaFirstPaintMs": 96.2, - "mpaFCPMs": 96.23, - "mpaINPMs": 13.72, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 92.2, "fcpMs": 92.33, "inpMs": 10.13, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 384, + "avgLatencyMs": 2.664, + "medianLatencyMs": 2.544, + "samples": 3755, + "bodySizeKb": 201.26, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 96.2, + "fcpMs": 96.23, + "inpMs": 13.72, + "runs": 5 } } diff --git a/packages/docs/src/content/runtime/app-react-router.json b/packages/docs/src/content/runtime/app-react-router.json index 230e6cdb..00e8e109 100644 --- a/packages/docs/src/content/runtime/app-react-router.json +++ b/packages/docs/src/content/runtime/app-react-router.json @@ -2,25 +2,29 @@ "name": "React Router", "package": "app-react-router", "isFocused": true, - "type": "ssr-app", + "type": "runtime-app", "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "7.10.1", - "ssrOpsPerSec": 64, - "ssrAvgLatencyMs": 15.528, - "ssrMedianLatencyMs": 0, - "ssrSamples": 644, - "ssrBodySizeKb": 211.14, - "ssrDuplicationFactor": 2, "order": 5, - "mpaFirstPaintMs": 141, - "mpaFCPMs": 140.92, - "mpaINPMs": 2.86, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 128.6, "fcpMs": 128.5, "inpMs": 15.03, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 64, + "avgLatencyMs": 15.528, + "medianLatencyMs": 0, + "samples": 644, + "bodySizeKb": 211.14, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 141, + "fcpMs": 140.92, + "inpMs": 2.86, + "runs": 5 } } diff --git a/packages/docs/src/content/runtime/app-solid-start.json b/packages/docs/src/content/runtime/app-solid-start.json index 7c30ce5a..8220fe26 100644 --- a/packages/docs/src/content/runtime/app-solid-start.json +++ b/packages/docs/src/content/runtime/app-solid-start.json @@ -2,25 +2,29 @@ "name": "SolidStart", "package": "app-solid-start", "isFocused": true, - "type": "ssr-app", + "type": "runtime-app", "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "1.2.1", - "ssrOpsPerSec": 404, - "ssrAvgLatencyMs": 2.616, - "ssrMedianLatencyMs": 2.478, - "ssrSamples": 3823, - "ssrBodySizeKb": 227.77, - "ssrDuplicationFactor": 2, "order": 6, - "mpaFirstPaintMs": 80, - "mpaFCPMs": 79.87, - "mpaINPMs": 11.96, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 92.2, "fcpMs": 91.91, "inpMs": 14.89, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 404, + "avgLatencyMs": 2.616, + "medianLatencyMs": 2.478, + "samples": 3823, + "bodySizeKb": 227.77, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 80, + "fcpMs": 79.87, + "inpMs": 11.96, + "runs": 5 } } diff --git a/packages/docs/src/content/runtime/app-sveltekit.json b/packages/docs/src/content/runtime/app-sveltekit.json index 0ee5f09e..ba2b90c3 100644 --- a/packages/docs/src/content/runtime/app-sveltekit.json +++ b/packages/docs/src/content/runtime/app-sveltekit.json @@ -2,25 +2,29 @@ "name": "SvelteKit", "package": "app-sveltekit", "isFocused": true, - "type": "ssr-app", + "type": "runtime-app", "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "2.49.4", - "ssrOpsPerSec": 437, - "ssrAvgLatencyMs": 2.337, - "ssrMedianLatencyMs": 2.221, - "ssrSamples": 4279, - "ssrBodySizeKb": 183.55, - "ssrDuplicationFactor": 2, "order": 7, - "mpaFirstPaintMs": 72.4, - "mpaFCPMs": 72.44, - "mpaINPMs": 0.45, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 106.6, "fcpMs": 106.59, "inpMs": 13.96, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 437, + "avgLatencyMs": 2.337, + "medianLatencyMs": 2.221, + "samples": 4279, + "bodySizeKb": 183.55, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 72.4, + "fcpMs": 72.44, + "inpMs": 0.45, + "runs": 5 } } diff --git a/packages/docs/src/content/runtime/app-tanstack-start-react.json b/packages/docs/src/content/runtime/app-tanstack-start-react.json index 20c551cd..06baf97a 100644 --- a/packages/docs/src/content/runtime/app-tanstack-start-react.json +++ b/packages/docs/src/content/runtime/app-tanstack-start-react.json @@ -2,25 +2,29 @@ "name": "TanStack Start", "package": "app-tanstack-start-react", "isFocused": true, - "type": "ssr-app", + "type": "runtime-app", "timingMeasuredAt": "2026-06-21T10:18:43.575Z", "runner": "ubuntu-latest", "frameworkVersion": "1.145.3", - "ssrOpsPerSec": 312, - "ssrAvgLatencyMs": 3.234, - "ssrMedianLatencyMs": 3.163, - "ssrSamples": 3092, - "ssrBodySizeKb": 193.53, - "ssrDuplicationFactor": 2, "order": 8, - "mpaFirstPaintMs": 81.2, - "mpaFCPMs": 81.16, - "mpaINPMs": 3.36, - "mpaRuns": 5, "clientSideRenderedTests": { "firstPaintMs": 144.6, "fcpMs": 144.81, "inpMs": 26.14, "runs": 5 + }, + "ssrRequestThroughputTests": { + "opsPerSec": 312, + "avgLatencyMs": 3.234, + "medianLatencyMs": 3.163, + "samples": 3092, + "bodySizeKb": 193.53, + "duplicationFactor": 2 + }, + "serverSideRenderedTests": { + "firstPaintMs": 81.2, + "fcpMs": 81.16, + "inpMs": 3.36, + "runs": 5 } } diff --git a/packages/docs/src/lib/collections.ts b/packages/docs/src/lib/collections.ts index c1966940..9ad7f2f4 100644 --- a/packages/docs/src/lib/collections.ts +++ b/packages/docs/src/lib/collections.ts @@ -8,21 +8,25 @@ export const starterStats = devtimeEntries .map((entry) => entry.data) .sort((a, b) => a.order - b.order) -export const ssrStats = runtimeEntries +export const ssrRequestThroughputStats = runtimeEntries .map((entry) => entry.data) .sort((a, b) => a.order - b.order) -export const mpaStats = runtimeEntries +export const serverSideRenderedStats = runtimeEntries .map((entry) => entry.data) .sort((a, b) => a.order - b.order) - .filter((f) => f?.name != null && Number.isFinite(f.mpaFirstPaintMs)) - .map((f) => ({ - name: f.name, - package: f.package, - isFocused: f.isFocused, - mpaFirstPaintMs: `${f.mpaFirstPaintMs}ms`, - mpaFCPMs: `${f.mpaFCPMs}ms`, - mpaINPMs: `${f.mpaINPMs}ms`, + .filter( + (framework) => + framework.serverSideRenderedTests != null && + Number.isFinite(framework.serverSideRenderedTests.firstPaintMs), + ) + .map((framework) => ({ + name: framework.name, + package: framework.package, + isFocused: framework.isFocused, + firstPaintMs: `${framework.serverSideRenderedTests!.firstPaintMs}ms`, + fcpMs: `${framework.serverSideRenderedTests!.fcpMs}ms`, + inpMs: `${framework.serverSideRenderedTests!.inpMs}ms`, })) export const clientSideRenderedStats = runtimeEntries @@ -80,27 +84,47 @@ export const chartDuplicateDependencyData = starterStats focused: f.isFocused, })) -export const chartMPAFPData = runtimeEntries +export const chartServerSideRenderedFPData = runtimeEntries .map((entry) => entry.data) .sort((a, b) => a.order - b.order) - .filter((f) => f?.name != null && Number.isFinite(f.mpaFirstPaintMs)) + .filter( + (f) => + f.serverSideRenderedTests != null && + Number.isFinite(f.serverSideRenderedTests.firstPaintMs), + ) .map((f) => ({ name: f.name, - value: f.mpaFirstPaintMs!, + value: f.serverSideRenderedTests!.firstPaintMs, focused: f.isFocused, })) -export const chartMPAFCPData = runtimeEntries +export const chartServerSideRenderedFCPData = runtimeEntries .map((entry) => entry.data) .sort((a, b) => a.order - b.order) - .filter((f) => f?.name != null && Number.isFinite(f.mpaFCPMs)) - .map((f) => ({ name: f.name, value: f.mpaFCPMs!, focused: f.isFocused })) + .filter( + (f) => + f.serverSideRenderedTests != null && + Number.isFinite(f.serverSideRenderedTests.fcpMs), + ) + .map((f) => ({ + name: f.name, + value: f.serverSideRenderedTests!.fcpMs, + focused: f.isFocused, + })) -export const chartMPAINPData = runtimeEntries +export const chartServerSideRenderedINPData = runtimeEntries .map((entry) => entry.data) .sort((a, b) => a.order - b.order) - .filter((f) => f?.name != null && Number.isFinite(f.mpaINPMs)) - .map((f) => ({ name: f.name, value: f.mpaINPMs!, focused: f.isFocused })) + .filter( + (f) => + f.serverSideRenderedTests != null && + Number.isFinite(f.serverSideRenderedTests.inpMs), + ) + .map((f) => ({ + name: f.name, + value: f.serverSideRenderedTests!.inpMs, + focused: f.isFocused, + })) export const chartClientSideRenderedFPData = runtimeEntries .map((entry) => entry.data) diff --git a/packages/docs/src/pages/framework/[slug].astro b/packages/docs/src/pages/framework/[slug].astro index 9b3e5f3c..daf0d689 100644 --- a/packages/docs/src/pages/framework/[slug].astro +++ b/packages/docs/src/pages/framework/[slug].astro @@ -2,10 +2,10 @@ import { getCollection } from 'astro:content' import BackLink from '../../components/BackLink.astro' import DevTimeChart from '../../components/DevTimeChart.astro' -import MPAStatsMethodologyNotes from '../../components/MPAStatsMethodologyNotes.astro' +import ServerSideRenderedStatsMethodologyNotes from '../../components/ServerSideRenderedStatsMethodologyNotes.astro' import PageHeader from '../../components/PageHeader.astro' import ClientSideRenderedStatsMethodologyNotes from '../../components/ClientSideRenderedStatsMethodologyNotes.astro' -import SSRStatsMethodologyNotes from '../../components/SSRStatsMethodologyNotes.astro' +import SSRRequestThroughputStatsMethodologyNotes from '../../components/SSRRequestThroughputStatsMethodologyNotes.astro' import StatsTable from '../../components/StatsTable.astro' import Layout from '../../layouts/Layout.astro' import { buildInstallData, depsStats } from '../../lib/collections' @@ -133,23 +133,24 @@ const buildData = [ }, ] -const ssrColumns = [ +const ssrRequestThroughputColumns = [ { key: 'name', header: 'Framework', nameCell: true }, - { key: 'ssrOpsPerSec', header: 'Ops/sec' }, - { key: 'ssrLatencyMs', header: 'Median Latency' }, - { key: 'ssrBodySizeKb', header: 'Body Size' }, - { key: 'ssrDuplicationFactor', header: 'Duplication' }, + { key: 'opsPerSec', header: 'Ops/sec' }, + { key: 'medianLatencyMs', header: 'Median Latency' }, + { key: 'bodySizeKb', header: 'Body Size' }, + { key: 'duplicationFactor', header: 'Duplication' }, ] -const ssrData = [ +const ssrRequestThroughputData = [ ...(baseline ? [ { name: baseline.name, - ssrOpsPerSec: baseline.ssrOpsPerSec?.toLocaleString() ?? '', - ssrLatencyMs: `${baseline.ssrMedianLatencyMs}ms`, - ssrBodySizeKb: `${baseline.ssrBodySizeKb}kb`, - ssrDuplicationFactor: `${baseline.ssrDuplicationFactor}x`, + opsPerSec: + baseline.ssrRequestThroughputTests.opsPerSec.toLocaleString(), + medianLatencyMs: `${baseline.ssrRequestThroughputTests.medianLatencyMs}ms`, + bodySizeKb: `${baseline.ssrRequestThroughputTests.bodySizeKb}kb`, + duplicationFactor: `${baseline.ssrRequestThroughputTests.duplicationFactor}x`, }, ] : []), @@ -157,10 +158,11 @@ const ssrData = [ ? [ { name: runtime.name, - ssrOpsPerSec: runtime.ssrOpsPerSec?.toLocaleString() ?? '', - ssrLatencyMs: `${runtime.ssrMedianLatencyMs}ms`, - ssrBodySizeKb: `${runtime.ssrBodySizeKb}kb`, - ssrDuplicationFactor: `${runtime.ssrDuplicationFactor}x`, + opsPerSec: + runtime.ssrRequestThroughputTests.opsPerSec.toLocaleString(), + medianLatencyMs: `${runtime.ssrRequestThroughputTests.medianLatencyMs}ms`, + bodySizeKb: `${runtime.ssrRequestThroughputTests.bodySizeKb}kb`, + duplicationFactor: `${runtime.ssrRequestThroughputTests.duplicationFactor}x`, }, ] : []), @@ -184,20 +186,20 @@ const clientSideRenderedData = runtime?.clientSideRenderedTests ] : [] -const mpaColumns = [ +const serverSideRenderedColumns = [ { key: 'name', header: 'Framework', nameCell: true }, - { key: 'mpaFirstPaintMs', header: 'First Paint' }, - { key: 'mpaFCPMs', header: 'FCP' }, - { key: 'mpaINPMs', header: 'INP' }, + { key: 'firstPaintMs', header: 'First Paint' }, + { key: 'fcpMs', header: 'FCP' }, + { key: 'inpMs', header: 'INP' }, ] -const mpaData = runtime +const serverSideRenderedData = runtime?.serverSideRenderedTests ? [ { name: runtime.name, - mpaFirstPaintMs: `${runtime.mpaFirstPaintMs}ms`, - mpaFCPMs: `${runtime.mpaFCPMs}ms`, - mpaINPMs: `${runtime.mpaINPMs}ms`, + firstPaintMs: `${runtime.serverSideRenderedTests.firstPaintMs}ms`, + fcpMs: `${runtime.serverSideRenderedTests.fcpMs}ms`, + inpMs: `${runtime.serverSideRenderedTests.inpMs}ms`, }, ] : [] @@ -325,13 +327,13 @@ const mpaData = runtime runtime && ( <>

    Runtime Performance

    -

    SSR Performance

    +

    SSR Request Throughput

    - +

    Client Side Rendered Performance

    -

    MPA Performance

    +

    Server Side Rendered Performance

    - + ) } diff --git a/packages/docs/src/pages/index.astro b/packages/docs/src/pages/index.astro index 51542ade..ea676fb5 100644 --- a/packages/docs/src/pages/index.astro +++ b/packages/docs/src/pages/index.astro @@ -2,13 +2,13 @@ import BuildSizeCharts from '../components/BuildSizeCharts.astro' import CoreJsTable from '../components/CoreJsTable.astro' import DependencyCharts from '../components/DependencyCharts.astro' -import MPACharts from '../components/MPACharts.astro' +import ServerSideRenderedCharts from '../components/ServerSideRenderedCharts.astro' import NodeModulesSizeCharts from '../components/NodeModulesSizeCharts.astro' import Description from '../components/Description.astro' import DetailsLink from '../components/DetailsLink.astro' import PageHeader from '../components/PageHeader.astro' import ClientSideRenderedCharts from '../components/ClientSideRenderedCharts.astro' -import SSRCharts from '../components/SSRCharts.astro' +import SSRRequestThroughputCharts from '../components/SSRRequestThroughputCharts.astro' import Layout from '../layouts/Layout.astro' import DepotLogo from '../assets/depot-logo-horizontal.svg' --- @@ -73,18 +73,24 @@ import DepotLogo from '../assets/depot-logo-horizontal.svg' label="Core-JS Polyfills in Dev Time Stats" />

    Runtime Performance

    -

    SSR Performance

    - - +

    SSR Request Throughput

    + +

    Client Side Performance

    -

    MPA Performance

    - - +

    Server Side Rendered Performance

    + +
    {entry.id} {entry.name} - View → + View →
    {entry.id} {entry.name} - View → + View →
    {entry.id} {entry.name}View →View →
    {entry.id} {entry.name} - View → + View →
    {entry.id} {entry.name} - + View → {entry.id} {entry.name} - + View →