Skip to content

test(benchmarks): profile unmodified React Link bundles - #8323

Open
schiller-manuel wants to merge 1 commit into
optimize-link-route-cachesfrom
optimize-link-benchmark-staging
Open

test(benchmarks): profile unmodified React Link bundles#8323
schiller-manuel wants to merge 1 commit into
optimize-link-route-cachesfrom
optimize-link-benchmark-staging

Conversation

@schiller-manuel

@schiller-manuel schiller-manuel commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

🎯 Changes

Add staging support that measures unmodified React Link bundles and verifies stable worker behavior.

This is PR 8 of a stacked series and is based on optimize-link-vue-subscriptions.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with the relevant test commands.
  • I fully understand the code in this pull request, including any code generated with AI assistance.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • Documentation

    • Added guidance about where built snapshots are staged for stable comparisons.
  • Tests

    • Added coverage verifying that worker processes load emitted JavaScript without unnecessary retranspilation.
    • Improved error reporting and cleanup validation for worker-based performance tests.
  • Refactor

    • Standardized staging-directory creation for link-performance benchmark runs.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: da9fcfd1-997e-443b-93e0-6a4292623edf

📥 Commits

Reviewing files that changed from the base of the PR and between a41f1f2 and 95e18fe.

📒 Files selected for processing (4)
  • benchmarks/client-nav/README.md
  • benchmarks/client-nav/link-performance/stable-runner.ts
  • benchmarks/client-nav/link-performance/stable-worker.test.ts
  • benchmarks/client-nav/link-performance/staging.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

The stable link-performance runner now uses a shared cache-based staging helper. A new worker test verifies that emitted JavaScript is not retranspiled by SWC. The README documents the staging location and loader behavior.

Changes

Link-performance staging

Layer / File(s) Summary
Cache staging integration
benchmarks/client-nav/link-performance/staging.ts, benchmarks/client-nav/link-performance/stable-runner.ts, benchmarks/client-nav/README.md
The runner creates temporary staging directories under node_modules/.cache through createStagingDirectory. The README documents this location and its loader purpose.
Worker loading regression test
benchmarks/client-nav/link-performance/stable-worker.test.ts
The test forks the worker with SWC registration, sends an initialization message, verifies the original function source in the error response, and removes temporary resources during cleanup.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 9b957

This benchmark-only change adds cache-backed staging and worker-loading coverage without changing production behavior, so it is ready to merge with normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 3 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The description includes all required sections. It explains the staging and worker changes, confirms the checklist items, and identifies the change as development-only with no release impact.
Title check ✅ Passed The title clearly describes the primary change: profiling unmodified React Link bundles in benchmark tests. It is concise and related to the pull request objectives.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 3 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch optimize-link-benchmark-staging

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@schiller-manuel
schiller-manuel force-pushed the optimize-link-benchmark-staging branch from 231787b to dfc59a2 Compare September 9, 2026 21:58
@nx-cloud

nx-cloud Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 9b957f3

Command Status Duration Result
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 33s View ↗
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 2m 11s View ↗

☁️ Nx Cloud last updated this comment at 2026-09-11 21:40:29 UTC

@pkg-pr-new

pkg-pr-new Bot commented Sep 9, 2026

Copy link
Copy Markdown
More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@8323

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@8323

@tanstack/eslint-plugin-start

npm i https://pkg.pr.new/@tanstack/eslint-plugin-start@8323

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@8323

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@8323

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@8323

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@8323

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@8323

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@8323

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@8323

@tanstack/react-start-rsc

npm i https://pkg.pr.new/@tanstack/react-start-rsc@8323

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@8323

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@8323

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@8323

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@8323

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@8323

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@8323

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@8323

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@8323

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@8323

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@8323

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@8323

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@8323

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@8323

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@8323

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@8323

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@8323

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@8323

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@8323

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@8323

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@8323

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@8323

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@8323

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@8323

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@8323

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@8323

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@8323

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@8323

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@8323

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@8323

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@8323

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@8323

commit: 9b957f3

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Benchmarks

  • Commit: deadedb094b2
  • Measured at: 2026-09-11T21:28:51.762Z
  • Baseline source: history:f021f6d1c6dc
  • Dashboard: bundle-size history

The following scenarios have bundle-size changes compared with the baseline:

Scenario Current (gzip) Initial (gzip) Raw Brotli Trend
react-router.minimal 84.0 KiB
+37 B
83.9 KiB
+31 B
262.0 KiB
-273 B
73.2 KiB
0 B
███████▁▁▁▁▃
react-router.full 87.5 KiB
+24 B
87.4 KiB
+31 B
273.7 KiB
-273 B
76.2 KiB
-24 B
███████▁▁▁▁▃
solid-router.minimal 33.5 KiB
+39 B
33.4 KiB
+44 B
96.5 KiB
-247 B
30.3 KiB
+2 B
▁▁▁▂▂▂▂▂▂▂▂█
solid-router.full 38.3 KiB
+53 B
38.2 KiB
+53 B
111.2 KiB
-247 B
34.5 KiB
-7 B
▁▁▁▂▂▂▂▂▂▂▂█
vue-router.minimal 49.5 KiB
-41 B
49.4 KiB
-41 B
137.7 KiB
-675 B
44.8 KiB
-27 B
███████▂▂▂▂▁
vue-router.full 55.1 KiB
-50 B
55.0 KiB
-49 B
155.9 KiB
-675 B
49.8 KiB
-5 B
███████▂▂▂▂▁
react-start.minimal 96.9 KiB
+34 B
96.8 KiB
+33 B
304.3 KiB
-274 B
84.1 KiB
-39 B
███████▁▁▁▁▃
react-start.query-integration 104.3 KiB
+22 B
104.1 KiB
+25 B
330.8 KiB
-274 B
90.4 KiB
+93 B
███████▁▁▁▁▂
react-start.deferred-hydration 97.6 KiB
+36 B
96.8 KiB
+34 B
305.7 KiB
-274 B
84.7 KiB
-55 B
███████▁▁▁▁▃
react-start.full 100.1 KiB
+43 B
100.0 KiB
+39 B
314.0 KiB
-274 B
86.9 KiB
+163 B
███████▁▁▁▁▃
react-start.rsbuild.minimal 100.1 KiB
+22 B
100.0 KiB
+22 B
314.6 KiB
-260 B
86.4 KiB
+6 B
███████▁▁▁▁▂
react-start.rsbuild.minimal-iife 100.6 KiB
+21 B
100.4 KiB
+21 B
315.5 KiB
-260 B
86.8 KiB
-39 B
███████▁▁▁▁▂
react-start.rsbuild.full 103.4 KiB
+10 B
103.3 KiB
+10 B
324.7 KiB
-260 B
89.2 KiB
+27 B
███████▁▁▁▁▂
solid-start.minimal 46.4 KiB
+53 B
46.3 KiB
+53 B
137.6 KiB
-247 B
41.2 KiB
+13 B
▂▂▂▁▁▁▁▁▁▁▁█
solid-start.deferred-hydration 49.5 KiB
+51 B
46.3 KiB
+49 B
145.0 KiB
-247 B
44.0 KiB
+29 B
▃▃▁▂▂▂▂▂▂▂▂█
solid-start.full 51.4 KiB
+64 B
51.3 KiB
+61 B
153.0 KiB
-247 B
45.7 KiB
+96 B
▁▁▁▁▁▁▁▁▁▁▁█
vue-start.minimal 65.7 KiB
-54 B
65.6 KiB
-56 B
188.5 KiB
-675 B
58.5 KiB
-23 B
███████▂▂▂▂▁
vue-start.full 69.6 KiB
-23 B
69.4 KiB
-21 B
200.8 KiB
-675 B
61.8 KiB
+33 B
███████▂▂▂▂▁

Current gzip tracks all emitted client JS chunks. Initial gzip tracks only the entry/import graph. Trend sparkline is historical current gzip ending with this PR measurement; lower is better.

@codspeed-hq

codspeed-hq Bot commented Sep 9, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 180 untouched benchmarks


Comparing optimize-link-benchmark-staging (9b957f3) with optimize-link-route-caches (0338650)

Open in CodSpeed

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

🚀 Changeset Version Preview

7 package(s) bumped directly, 22 bumped as dependents.

🟩 Patch bumps

Package Version Reason
@tanstack/history 1.162.3 → 1.162.4 Changeset
@tanstack/react-router 1.170.35 → 1.170.36 Changeset
@tanstack/router-core 1.171.29 → 1.171.30 Changeset
@tanstack/router-devtools-core 1.168.1 → 1.168.2 Changeset
@tanstack/solid-router 1.170.33 → 1.170.34 Changeset
@tanstack/start-server-core 1.169.34 → 1.169.35 Changeset
@tanstack/vue-router 1.170.32 → 1.170.33 Changeset
@tanstack/react-router-devtools 1.167.1 → 1.167.2 Dependent
@tanstack/react-start 1.168.52 → 1.168.53 Dependent
@tanstack/react-start-client 1.168.33 → 1.168.34 Dependent
@tanstack/react-start-rsc 0.1.51 → 0.1.52 Dependent
@tanstack/react-start-server 1.167.40 → 1.167.41 Dependent
@tanstack/router-cli 1.167.35 → 1.167.36 Dependent
@tanstack/router-devtools 1.167.1 → 1.167.2 Dependent
@tanstack/router-generator 1.167.35 → 1.167.36 Dependent
@tanstack/router-plugin 1.168.37 → 1.168.38 Dependent
@tanstack/router-vite-plugin 1.167.37 → 1.167.38 Dependent
@tanstack/solid-router-devtools 1.167.1 → 1.167.2 Dependent
@tanstack/solid-start 1.168.50 → 1.168.51 Dependent
@tanstack/solid-start-client 1.168.32 → 1.168.33 Dependent
@tanstack/solid-start-server 1.167.39 → 1.167.40 Dependent
@tanstack/start-client-core 1.170.29 → 1.170.30 Dependent
@tanstack/start-plugin-core 1.171.42 → 1.171.43 Dependent
@tanstack/start-static-server-functions 1.167.34 → 1.167.35 Dependent
@tanstack/start-storage-context 1.167.31 → 1.167.32 Dependent
@tanstack/vue-router-devtools 1.167.1 → 1.167.2 Dependent
@tanstack/vue-start 1.168.49 → 1.168.50 Dependent
@tanstack/vue-start-client 1.167.35 → 1.167.36 Dependent
@tanstack/vue-start-server 1.167.39 → 1.167.40 Dependent

@schiller-manuel
schiller-manuel force-pushed the optimize-link-benchmark-staging branch from dfc59a2 to ee7de43 Compare September 9, 2026 23:23
@schiller-manuel
schiller-manuel force-pushed the optimize-link-benchmark-staging branch 2 times, most recently from c019c22 to fd0c7f2 Compare September 10, 2026 20:29
@schiller-manuel
schiller-manuel requested a review from a team as a code owner September 10, 2026 20:29
@schiller-manuel
schiller-manuel changed the base branch from optimize-link-vue-subscriptions to optimize-link-route-caches September 10, 2026 20:29
@schiller-manuel
schiller-manuel force-pushed the optimize-link-benchmark-staging branch from fd0c7f2 to 95e18fe Compare September 10, 2026 21:12
@schiller-manuel
schiller-manuel added this pull request to stack #8346 September 10, 2026 21:30

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

At least one additional CI pipeline execution has run since the conclusion below was written and it may no longer be applicable.

Nx Cloud is proposing a fix for your failed CI:

We converted the static import { createClientScenario, createSsrScenario } in stable-worker.ts to dynamic imports deferred until after the bundle is successfully loaded. This fixes the worker crash caused by @swc-node/register's ESM resolver failing to find @tanstack/history (transitively required by ./scenario) at worker startup when forked with the workspace root as cwd. Because the new test's fake bundle throws on import, the ./scenario dynamic import is never reached, allowing the worker to start cleanly and return the expected error response.

Tip

We verified this fix by re-running @benchmarks/react-link-performance:test:unit.

diff --git a/benchmarks/client-nav/link-performance/stable-worker.ts b/benchmarks/client-nav/link-performance/stable-worker.ts
index d98679dc..a8e32386 100644
--- a/benchmarks/client-nav/link-performance/stable-worker.ts
+++ b/benchmarks/client-nav/link-performance/stable-worker.ts
@@ -1,5 +1,4 @@
 import { pathToFileURL } from 'node:url'
-import { createClientScenario, createSsrScenario } from './scenario'
 import type { LinkScenario } from './scenario'
 import type { WorkerRequest, WorkerResponse } from './worker-protocol'
 import type * as ClientApp from './src/client'
@@ -36,12 +35,14 @@ async function handle(request: WorkerRequest) {
       if (app.serverEnvironment !== false) {
         throw new Error('Expected a production client bundle')
       }
+      const { createClientScenario } = await import('./scenario')
       scenario = createClientScenario(app, request.caseId)
     } else {
       const app: typeof SsrApp = await import(bundleUrl.href)
       if (app.serverEnvironment !== true) {
         throw new Error('Expected a production SSR bundle')
       }
+      const { createSsrScenario } = await import('./scenario')
       scenario = createSsrScenario(app, request.caseId)
     }
     scenarios[request.variant] = scenario

Apply fix via Nx Cloud  Reject fix via Nx Cloud


Or Apply changes locally with:

npx nx-cloud apply-locally dPaJ-U327

Apply fix locally with your editor ↗   View interactive diff ↗



🎓 Learn more about Self-Healing CI on nx.dev

Keep comparison snapshots in SWC's existing node_modules exclusion so emitted JavaScript is not retranspiled and source-map positions remain valid. Preserve asynchronous ESM loading and add a failing-before source-integrity regression.

Four-replica identical-bundle calibration: client shared-params CPU +0.92% [-4.14%, +6.24%], wall +1.03% [-4.55%, +6.93%]; SSR CPU +0.17% [-6.32%, +7.11%], wall +0.15% [-6.44%, +7.21%]. Intervals include zero; no speedup is claimed. Production code is unchanged; baseline React Router gzip is 85797/89379 bytes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@schiller-manuel
schiller-manuel force-pushed the optimize-link-benchmark-staging branch from 95e18fe to 9b957f3 Compare September 11, 2026 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant