Skip to content

Fix/rsbuild static chunk availability - #8780

Open
LadyBluenotes wants to merge 5 commits into
mainfrom
fix/rsbuild-static-chunk-availability
Open

LadyBluenotes wants to merge 5 commits into
mainfrom
fix/rsbuild-static-chunk-availability

Conversation

@LadyBluenotes

@LadyBluenotes LadyBluenotes commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

🎯 Changes

Follow-up to #8695 (#8415, #8511). computeStaticDependencyChunks() treated a chunk as available if any group of the importing chunk, or any ancestor, contained it. A shared chunk in sibling route groups therefore got import edges to each route's copy of a duplicated module, and the manifest gave route A route C's CSS and preloads.

Rspack and webpack combine availability across parents with intersection (intersect_with in code_splitter.rs; minAvailableModules &= availableModules in buildChunkGraph.js). This PR does the same per chunk group: own chunks plus the intersection of the parents' availability. It iterates to a fixed point that only shrinks, so cyclic async graphs terminate and give the same result in any order. A chunk's availability is the intersection across its groups.

New Rspack-fixture tests: sibling duplication, a two-parent lazy group, a dependency available on every path, and a ping/pong cycle in both orders.

AI disclosure: drafted with an AI assistant; reviewed and verified by me.

✅ 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.

Summary by CodeRabbit

  • Bug Fixes

    • Improved static chunk loading for applications built with Rsbuild.
    • Prevented shared chunks from including CSS and preload links intended for sibling routes.
    • Preserved route-specific links to split chunks used by shared code.
    • Improved resource ordering and delivery across nested, lazy, and cyclic routes, including deferred styles for root boundaries.
  • Tests

    • Expanded coverage for shared chunks, route-specific resources, CSS ordering, preloads, and deferred hydration.

@changeset-bot

changeset-bot Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4542078

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

@nx-cloud

nx-cloud Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 4542078

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ❌ Failed 16m 38s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 26s View ↗

☁️ Nx Cloud last updated this comment at 2026-10-29 19:24:16 UTC

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 8bb4af8 and 4542078.

Files selected for processing: 8
  • e2e/react-start/deferred-hydration/src/routes/__root.tsx
  • e2e/react-start/deferred-hydration/src/shared/root-deferred.module.css
  • e2e/react-start/deferred-hydration/tests/hydration.spec.ts
  • packages/start-plugin-core/src/rsbuild/normalized-client-build.ts
  • packages/start-plugin-core/src/start-manifest-plugin/manifestBuilder.ts
  • packages/start-plugin-core/src/types.ts
  • packages/start-plugin-core/src/vite/start-manifest-plugin/normalized-client-build.ts
  • packages/start-plugin-core/tests/rsbuild/normalized-client-build.test.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.

Walkthrough

The Rsbuild client-build normalizer now groups entry and route assets based on chunk-group availability. The manifest builder uses those groups to create route resources. Tests cover shared chunks, route-specific assets, hydration CSS, and asset ordering.

Changes: Rsbuild route-scoped client assets

Layer / File(s) Summary
Asset contract and normalization
packages/start-plugin-core/src/types.ts, packages/start-plugin-core/src/rsbuild/normalized-client-build.ts, packages/start-plugin-core/src/vite/start-manifest-plugin/normalized-client-build.ts
The client build types now distinguish chunk builds from grouped builds. Rsbuild normalization maps route origins to route asset groups and collects entry, preload, and CSS assets. The Vite normalizer continues to return the chunk-build type.
Manifest route resources
packages/start-plugin-core/src/start-manifest-plugin/manifestBuilder.ts
The manifest builder selects the grouped-build path when route assets are present. It maps route preloads and CSS to manifest resources, merges entry assets into the root, and emits entry scripts.
Asset behavior validation
packages/start-plugin-core/tests/rsbuild/normalized-client-build.test.ts, e2e/react-start/deferred-hydration/src/routes/__root.tsx, e2e/react-start/deferred-hydration/src/shared/root-deferred.module.css, e2e/react-start/deferred-hydration/tests/hydration.spec.ts, .changeset/rsbuild-static-chunk-availability.md
Tests cover shared chunks, lazy-group dependencies, route assets, asset ordering, and Windows paths. The deferred-hydration example and test cover CSS in a root hydration boundary. A changeset records a patch release.

Priority: Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant RspackCompilation
  participant normalizeRspackClientBuild
  participant buildStartManifest
  RspackCompilation->>normalizeRspackClientBuild: Provide entrypoint and chunk groups
  normalizeRspackClientBuild->>buildStartManifest: Return entry and route assets
  buildStartManifest->>buildStartManifest: Map route preloads and CSS to manifest resources
Loading

Possibly related issues

Possibly related PRs

  • TanStack/router#8800: It caches the normalized build and fingerprints chunk groups used by this PR’s group-based normalization.

Suggested reviewers: schiller-manuel, czearing

Merge Risk: Minimal · up to 45420

The change makes Rsbuild static chunk availability follow chunk-group parent paths, which should stop sibling route assets from leaking into the manifest. No actionable merge-blocking risk was found, and tests cover the main cases, including shared chunks, two-parent groups and cycles.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title "Fix/rsbuild static chunk availability" names the main change: the fix to static dependency chunk availability for Rsbuild (computeStaticDependencyChunks now intersects parent availability p…
Description check Passed The description follows the template: it has a Changes section explaining the bug (shared chunks in sibling route groups linking another route's CSS and preloads), the fix (per-group intersection of p…
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 "Fix/rsbuild static chunk availability" names the main change: the fix to static dependency chunk availability for Rsbuild (computeStaticDependencyChunks now intersects parent availability per chunk group). It is concise and specific. The branch-style prefix "Fix/" is a minor style issue but does not affect relevance.

Full details: Description check

Explanation

The description follows the template: it has a Changes section explaining the bug (shared chunks in sibling route groups linking another route's CSS and preloads), the fix (per-group intersection of parent availability with a fixed-point iteration), and the tests added. It includes the checklist with the items checked and the release impact section with the changeset box checked. The AI disclosure is present. The description does not mention the changeset file by name, and it does not state the scope of the e2e deferred-hydration changes, but these gaps are non-critical.

Full details: Docstring Coverage

Explanation

Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 13 functions across 7 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • 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

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

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

🚀 Changeset Version Preview

1 package(s) bumped directly, 4 bumped as dependents.

🟩 Patch bumps

Package Version Reason
@tanstack/start-plugin-core 1.171.55 → 1.171.56 Changeset
@tanstack/react-start 1.169.4 → 1.169.5 Dependent
@tanstack/react-start-rsc 0.1.65 → 0.1.66 Dependent
@tanstack/solid-start 1.169.4 → 1.169.5 Dependent
@tanstack/vue-start 1.169.4 → 1.169.5 Dependent

@codspeed

codspeed Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Merging this PR will improve performance by 3.42%

2 warnings

⚠️ 51 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

⚠️ Base and head ran on different runner types

Some benchmarks with significant performance changes were compared across different runner types, so the changes might not come from the code. Run base and head on the same runner type, or use CodSpeed Macro Runners for more stable results.

Learn more about Macro Runners

Open the report in CodSpeed to investigate

⚡ 2 improved benchmarks
✅ 192 untouched benchmarks
⏩ 3 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
⚡ Memory mem client navigation-churn (solid) 109.7 KB 105.7 KB +3.8%
⚡ Memory mem client unique-location-churn (vue) 82.8 KB 80.3 KB +3.03%

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing fix/rsbuild-static-chunk-availability (4542078) with main (da2adec)

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. ↩

@github-actions

Copy link
Copy Markdown
Contributor

Bundle Size Benchmarks

This pull request does not affect bundle size in any measured scenario.

@pkg-pr-new

pkg-pr-new Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
More templates

@tanstack/arktype-adapter

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

@tanstack/eslint-plugin-router

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

@tanstack/eslint-plugin-start

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

@tanstack/history

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-rsc

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-fn-stubs

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

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

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: 4542078

Sarah Gerrard and others added 3 commits October 21, 2026 12:23
…cross loading paths

A shared chunk recorded static imports to every chunk in the union of its groups and their ancestors, so it pointed at each sibling route's copy of a duplicated module. Compute availability per chunk group as its own chunks plus the intersection of its parents, iterate to a shrinking fixed point for cyclic async graphs, and intersect across the chunk's groups.
Sheraff added a commit that referenced this pull request Oct 25, 2026
…aring a module

The route CSS rows (SPEC J2.22) now live in route-css-cases.ts and run
for each bundler from its own file: known-bugs-route-css.test.ts on Vite
dev and build, known-bugs-route-css-rsbuild.test.ts on the Rsbuild dev
server and an Rsbuild production build served as `rsbuild preview` does
(new StartBuild.preview() of the build harness).

New rows: two routes whose components import their own CSS and share a
module. On a route, the other route's styles must not apply, after a
client-side navigation and in the page the server renders there. Vite
passes; on Rsbuild, with the shared module in a chunk of its own, the
page links the other route's stylesheet (Start's Rsbuild manifest, #8780),
pinned as a separate known bug.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sheraff added a commit that referenced this pull request Oct 25, 2026
…y when every group of the importer has it (#8780)

computeStaticDependencyChunks took the union of the chunks of every group a
shared chunk belongs to, so a module duplicated into each route's chunk made
the shared chunk depend on both routes' chunks and each route's page linked
the other route's CSS. The intersection over the groups (with their
ancestors) keeps a per-group dependency out of the shared chunk's imports.
Flips the four shares-module rows of known-bugs-route-css-rsbuild.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sheraff added a commit that referenced this pull request Oct 26, 2026
The shows-component, shows-error and shows-not-found rows return to
known-bug pins on Vite and Rsbuild, as in the oracle; the Rsbuild
shares-module rows (#8780) keep passing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SyMind

SyMind commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

@LadyBluenotes I think we could simplify this by collecting assets per route’s chunk group, rather than reconstructing a global chunk.imports graph from module dependencies.

A shared chunk can belong to several loading contexts, and its dependencies may be provided by different chunks in each context. Flattening those relationships into a single imports list loses that distinction and can pull sibling route assets into the manifest.

My suggestion is:

  1. Iterate over compilation.chunkGroups and use group.origins to identify the ?tsr-split=... imports.
  2. Resolve those requests to route file paths and build a route → chunk groups mapping. We need to preserve multiple groups per route and handle relative requests and aliases.
  3. Collect assets directly from each group’s chunks, plus chunks guaranteed to be available through every parent path. Keep the parent intersection and cycle handling, without expanding a shared chunk into its other groups.
  4. Pass the resulting per-route JS/CSS assets to the manifest builder directly, instead of converting them back into chunk import edges.

I implemented a prototype here. The regression scenarios from this PR pass after adapting the assertions to the final route manifest, along with the Rsbuild CSS, deferred hydration, and HMR integration tests.

Collect JavaScript and CSS from route chunk groups instead of reconstructing global chunk imports. Preserve parent-path intersection and the Vite chunk-based manifest path.

Include entry-owned hydration styles so root-level deferred content is styled without loading its JavaScript. Cover shared loading groups and root hydration with compiler and production browser regressions.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants