Skip to content

perf(start-plugin-core): speed up rsbuild client build normalization - #8588

Open
guru-irl wants to merge 12 commits into
TanStack:mainfrom
guru-irl:perf/rsbuild-client-build-capture
Open

guru-irl wants to merge 12 commits into
TanStack:mainfrom
guru-irl:perf/rsbuild-client-build-capture

Conversation

@guru-irl

@guru-irl guru-irl commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

🎯 Changes

normalizeRspackClientBuild converts the Rspack client compilation into the data used to build the Start manifest. It runs on every Rsbuild build and on every dev rebuild. This PR makes it faster for builds with many chunks. The output does not change.

  • Chunk and chunk group properties (files, auxiliaryFiles, groupsIterable, chunks, childrenIterable) are now read once per call. Rspack builds a new collection on every read, and the previous code read them many times per chunk.
  • Modules are now read only from chunks that contain a route-split or hydration module. The previous code called getChunkModules for every chunk.

Benchmarks

Median of 21 runs of normalizeRspackClientBuild on generated apps, Rspack 2.2.3, production unless noted:

App Chunks Chunk groups main This PR Speedup
Routes and shared vendor chunks 760 481 61.1 ms 14.3 ms 4.3x
Large 2,456 901 131.8 ms 36.5 ms 3.6x
Large (development) 2,456 901 138.6 ms 37.3 ms 3.7x
Shared modules in route chunks 1,397 901 97.0 ms 39.4 ms 2.5x
Many non-route async chunks 3,245 3,101 235.1 ms 53.4 ms 4.4x

For each app, the output was compared with main on Rspack 2.0.0, 2.1.1 and 2.2.3 and was identical.

Tests

  • New unit tests in normalized-client-build.test.ts use a small fake chunk graph. They check that:
    • imports and dynamic imports are listed in the same order as before (this test also passes on main);
    • modules are read only from chunks with a route-split or hydration module;
    • each chunk and chunk group property is read at most once.
  • @tanstack/start-plugin-core test:unit, test:types and test:eslint pass.
  • These Rsbuild e2e suites pass:
    • react-start rsbuild, rsc-rsbuild and hmr
    • deferred-hydration (production and dev)
    • solid-start deferred-hydration
    • css-inline, with and without transform assets

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with the relevant test commands, or tests do not apply to this pull request.
  • 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

  • Performance
    • Improved Start manifest generation speed for Rsbuild client builds with many chunks, reducing build-time overhead in larger applications. Generated manifests continue to include route and hydration information, with static and dynamic imports kept in traversal order. This helps larger builds complete more efficiently while preserving the manifest details and dependency ordering applications rely on.

Remove the real Rspack compile fixture, its helper and snapshots. Cover the
same behavior in the existing normalized-client-build unit tests with a small
fake chunk graph: output order of imports and dynamic imports, module reads
only for route-split and hydration chunks, and one read per chunk graph
property.
…eader

Clarify comments on the chunk scan and read helpers, read child groups
directly since their merged JS files are already cached per group, keep the
unrelated isManifestJsAsset line unchanged, and assert the set of chunks whose
modules are read.
@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

Rsbuild client build normalization now caches chunk and group graph reads for asset and dependency collection. It selects chunks containing tagged modules for route and hydration metadata. Tests cover normalized output, graph-read limits, and metadata in concatenated modules.

Changes: Rsbuild Client Build Normalization

Layer / File(s) Summary
Cached graph reads and metadata selection
packages/start-plugin-core/src/rsbuild/normalized-client-build.ts
A per-normalization reader caches chunk and group data. It derives ordered, deduplicated JavaScript, CSS, and dynamic-import lists. Route and hydration metadata extraction targets chunks containing tagged modules, including nested concatenated modules.
Dependency and normalization integration
packages/start-plugin-core/src/rsbuild/normalized-client-build.ts, packages/start-plugin-core/tests/rsbuild/normalized-client-build.test.ts, .changeset/rsbuild-client-build-capture.md
Entrypoints, static dependencies, CSS-only dependencies, and RSC assets use the shared reader. Tests cover normalized output, graph and module reads, and concatenated-module metadata. The changeset describes faster manifest generation for Rsbuild client builds with many chunks.

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

Change: Refactor

Suggested reviewers: schiller-manuel, ladybluenotes, sheraff

Merge Risk: Minimal · up to 9c9df

This change speeds up Rsbuild client build normalization without changing its output. No merge-blocking risk was identified.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title names the scope (start-plugin-core), the change type (perf), and the target (rsbuild client build normalization). It matches the main change: normalizeRspackClientBuild now reads chunk prope…
Description check Passed The description follows the template. It has the Changes section with motivation, benchmark data, and test notes. The checklist is filled in, and both release-impact boxes are handled (changeset is ma…
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.
Full details: Title check

Explanation

The title names the scope (start-plugin-core), the change type (perf), and the target (rsbuild client build normalization). It matches the main change: normalizeRspackClientBuild now reads chunk properties once and reads modules only from tagged chunks. The title is specific and short, so it passes.

Full details: Description check

Explanation

The description follows the template. It has the Changes section with motivation, benchmark data, and test notes. The checklist is filled in, and both release-impact boxes are handled (changeset is marked as generated). It discloses no AI authorship, which the template's AI-authored rules ask for. The PR objectives say the author used AI assistance in part, but the description does not state that. The description is otherwise complete.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between c2dfffe and 9c9df50.

Files selected for processing: 1

  • packages/start-plugin-core/src/rsbuild/normalized-client-build.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

@nx-cloud

nx-cloud Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit aa5c89c

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

☁️ Nx Cloud last updated this comment at 2026-10-02 08:56:50 UTC

@pkg-pr-new

pkg-pr-new Bot commented Oct 2, 2026

Copy link
Copy Markdown
More templates

@tanstack/arktype-adapter

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

@tanstack/eslint-plugin-router

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

@tanstack/eslint-plugin-start

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-rsc

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-fn-stubs

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

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

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: aa5c89c

@codspeed

codspeed Bot commented Oct 2, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 14.02%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 1 regressed benchmark
✅ 190 untouched benchmarks
⏩ 3 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ Simulation hydrate restored route state and mixed Links (react) 213.4 ms 248.2 ms -14.02%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing guru-irl:perf/rsbuild-client-build-capture (aa5c89c) with main (1f0f20a)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@guru-irl

guru-irl commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author
Screenshot 2026-10-02 at 16 29 38

The performance benchmark was executed on 2 different machine configs. The other 2 checks are failing with 403s

@guru-irl

guru-irl commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

@schiller-manuel can I get a review? This cuts hot reloads by ~30% in large applications

@changeset-bot

changeset-bot Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9c9df50

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@tanstack/start-plugin-core Patch
@tanstack/react-start-rsc Patch
@tanstack/react-start Patch
@tanstack/solid-start Patch
@tanstack/vue-start Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

This branch has not been deployed

No deployments
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