Skip to content

Fix prerendering issues of Brouter (#12830) - #12831

Merged
msynk merged 4 commits into
bitfoundation:developfrom
msynk:12830-brouter-prerendering-issues
Aug 6, 2026
Merged

Fix prerendering issues of Brouter (#12830)#12831
msynk merged 4 commits into
bitfoundation:developfrom
msynk:12830-brouter-prerendering-issues

Conversation

@msynk

@msynk msynk commented Aug 5, 2026

Copy link
Copy Markdown
Member

closes #12830

Summary by CodeRabbit

  • Bug Fixes

    • Initial navigation now displays the correct route during the first render, including nested and wrapped routes.
    • Routes registered shortly after mounting are detected and matched without requiring another navigation.
    • Prevented late, unrelated route registrations from replacing the currently selected route.
    • Improved navigation stability and handling across interactive and server-rendered environments.
  • Tests

    • Added comprehensive coverage for initial rendering, nested routes, wrappers, late registration, and authorization failures.

@msynk
msynk requested a review from yasmoradi August 5, 2026 12:04
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b7f8135d-6c4c-4ddb-9b02-7e927efb38f3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Brouter now starts initial navigation through a render-tree sentinel during the first render batch. It tracks route-registration versions and defers rematching until navigation is idle. New tests cover flat, nested, wrapped, late-registered, and prerendered routes.

Changes

Routing boot and rematch

Layer / File(s) Summary
Boot-sentinel initial navigation
src/Brouter/Bit.Brouter/Components/Brouter.cs, src/Brouter/Bit.Brouter/Components/BrouterInitializer.cs, src/Brouter/Tests/Bit.Brouter.Tests/*
Initial navigation moves from OnInitializedAsync to the boot sentinel. The initializer waits for route registration to settle before invoking RunInitialNavigationAsync.
Deferred late-route rematching
src/Brouter/Bit.Brouter/Components/Brouter.cs, src/Brouter/Bit.Brouter/Components/BrouterInitializer.cs, src/Brouter/Tests/Bit.Brouter.Tests/*
Route registration changes increment a version. Rematching waits for active navigation pipelines to finish and uses replacement navigation only when the committed route changes.
Initial-mount and routing validation
src/Brouter/Tests/Bit.Brouter.Tests/*
Tests cover first-batch rendering, nested and wrapped routes, late registration, prerendering, unchanged winners, and synchronous authorization failures.

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

Suggested reviewers: yasmoradi

Poem

A rabbit watched routes settle in line,
Then hopped through the first render just fine.
Late paths appeared, winners may change,
Idle rematches kept the flow in range.
No empty flash, just content on time.

🚥 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: fixing Brouter prerendering issues.
Linked Issues check ✅ Passed The changes address hydration flashes by enabling first-batch route rendering and validating prerendered and late-registered routes [#12830].
Out of Scope Changes check ✅ Passed The production changes and tests support Brouter prerendering, initial navigation, late registration, and related exception behavior.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Brouter/Bit.Brouter/Components/Brouter.cs (1)

722-752: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Route exceptions from the discarded rematch task.

ScheduleLateRegistrationRematch discards the task returned by InvokeAsync. ProcessNavigationAsync handles most failures internally, but it deliberately rethrows NavigationException (see Line 2549). On this path that exception faults a task nobody observes, so an SSR redirect triggered by a late-registration rematch is lost silently.

Wrap the awaited call so the failure reaches SafeInvokeOnError instead of an unobserved task.

♻️ Proposed guard around the deferred navigation
-            await ProcessNavigationAsync(CurrentLocation, CurrentLocation, decisionAlreadyMade: false, BrouterNavigationType.Replace);
+            try
+            {
+                await ProcessNavigationAsync(CurrentLocation, CurrentLocation, decisionAlreadyMade: false, BrouterNavigationType.Replace);
+            }
+            catch (Exception ex)
+            {
+                // Nothing awaits this scheduled task, so an escaping exception (notably the SSR
+                // NavigationException redirect signal) would otherwise be swallowed.
+                await SafeInvokeOnError(CurrentLocation, CurrentLocation, ex);
+            }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Brouter/Bit.Brouter/Components/Brouter.cs` around lines 722 - 752, Update
ScheduleLateRegistrationRematch to catch NavigationException from the awaited
ProcessNavigationAsync call and forward it to SafeInvokeOnError, ensuring
redirects or other route exceptions from the discarded InvokeAsync task are
observed without changing the existing rematch scheduling behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Brouter/Bit.Brouter/Components/Brouter.cs`:
- Around line 2613-2622: Move the _processingNavigation decrement and its
outermost-frame rematch check to the beginning of the pipeline’s finally block,
before any await or other potentially throwing cleanup such as
CompleteViewTransitionAsync. Preserve the existing condition and
ScheduleLateRegistrationRematch behavior so the increment at the pipeline entry
is always balanced, including when cleanup throws.

---

Nitpick comments:
In `@src/Brouter/Bit.Brouter/Components/Brouter.cs`:
- Around line 722-752: Update ScheduleLateRegistrationRematch to catch
NavigationException from the awaited ProcessNavigationAsync call and forward it
to SafeInvokeOnError, ensuring redirects or other route exceptions from the
discarded InvokeAsync task are observed without changing the existing rematch
scheduling behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e5103ee7-1ace-4536-ad76-183be511e5ad

📥 Commits

Reviewing files that changed from the base of the PR and between 679ac06 and 9130d7e.

📒 Files selected for processing (14)
  • src/Brouter/Bit.Brouter/Components/Brouter.cs
  • src/Brouter/Bit.Brouter/Components/BrouterInitializer.cs
  • src/Brouter/Tests/Bit.Brouter.Tests/AmbiguousRouteTests.cs
  • src/Brouter/Tests/Bit.Brouter.Tests/BrouterAuthorizationTests.cs
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialBatchProbe.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountContent.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountDeepWrappedHost.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountHost.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountLateRouteHost.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountNestedHost.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountState.cs
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountTests.cs
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountWrappedHost.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountWrapper.razor

Comment thread src/Brouter/Bit.Brouter/Components/Brouter.cs Outdated
@msynk

msynk commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full-review

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

@msynk, I will perform a complete review of pull request #12831.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Brouter/Tests/Bit.Brouter.Tests/AmbiguousRouteTests.cs`:
- Around line 117-119: Update the stale member reference in the comment within
AmbiguousRouteTests to use Brouter.RequestLateRegistrationRematch instead of the
removed Brouter.ScheduleLateRegistrationRematch, leaving the surrounding
explanation unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 01ccd235-8bd0-492d-8f1e-32b1bdbd6fc9

📥 Commits

Reviewing files that changed from the base of the PR and between 679ac06 and e649587.

📒 Files selected for processing (16)
  • src/Brouter/Bit.Brouter/Components/Brouter.cs
  • src/Brouter/Bit.Brouter/Components/BrouterInitializer.cs
  • src/Brouter/Tests/Bit.Brouter.Tests/AmbiguousRouteTests.cs
  • src/Brouter/Tests/Bit.Brouter.Tests/BrouterAuthorizationTests.cs
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialBatchProbe.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountContent.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountDeepWrappedHost.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountHost.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountLateRouteHost.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountNestedHost.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountState.cs
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountTests.cs
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountWrappedHost.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/InitialMountWrapper.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/LateRegisteredAuthHost.razor
  • src/Brouter/Tests/Bit.Brouter.Tests/PrerenderMountTests.cs

Comment thread src/Brouter/Tests/Bit.Brouter.Tests/AmbiguousRouteTests.cs
@msynk
msynk merged commit 2fa4493 into bitfoundation:develop Aug 6, 2026
3 checks passed
@msynk
msynk deleted the 12830-brouter-prerendering-issues branch August 6, 2026 04:54
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.

Prerendering issues of the Brouter

1 participant