Skip to content

refactor(router): decompose monolithic router into single-responsibility modules#268

Merged
mohamedmansour merged 3 commits intomainfrom
chore/refactor-router
Apr 23, 2026
Merged

refactor(router): decompose monolithic router into single-responsibility modules#268
mohamedmansour merged 3 commits intomainfrom
chore/refactor-router

Conversation

@mohamedmansour
Copy link
Copy Markdown
Contributor

What changed

Broke the ~1,800-line monolith router.ts into 8 focused modules and optimized the Rust-side route handler for faster SSR rendering.

Client — webui-router

New module Responsibility
cache.ts NavigationCache — LRU eviction + tag-based invalidation

router.ts is now a thin orchestrator (~80 lines of imports + wiring) that delegates all heavy lifting to these extracted modules.

Server — webui-handler (Rust)

  • ProtocolIndex — pre-computes component bit-index, compiled route cache (CompiledRouteCache), and per-fragment component closures once per protocol load instead of per-request.
  • CompiledRouteCache — caches parsed route template patterns (Vec<SegmentPattern>) via match_route_cached(), eliminating per-request parsing allocations in the route-matching hot path.
  • data-ri attribute — matched SSR routes now emit a chain index (data-ri="N") so the client can bind routes in O(1) instead of DOM-walking.
  • window.__webui bootstrap object — replaces scattered <meta name="webui-inventory"> and <script id="webui-chain"> tags with a single consolidated inline script containing chain, inventory, nonce, css, and styles.
  • write_usize() — writes numeric data-ri values directly to the response writer, avoiding format! heap allocation.

Other updates

  • DESIGN.md — updated to reflect the new SSR bootstrap contract, ProtocolIndex, partial response fields (allowedQuery, keepAlive, cacheControl), and hydration flow.
  • docs/guide/concepts/routing.md — updated user-facing routing docs.
  • webui-framework — adjusted template/element APIs for the new registration flow.
  • Tests — updated unit and E2E tests across router, handler, commerce example, and routes/todo examples.

…ity modules

## What changed

Broke the ~1,800-line monolith `router.ts` into **8 focused modules** and
optimized the Rust-side route handler for faster SSR rendering.

### Client — `webui-router`

| New module | Responsibility |
|---|---|
| `cache.ts` | `NavigationCache` — LRU eviction + tag-based invalidation |
| `chain.ts` | Route-chain building from SSR and reconciliation (diff old vs new) |
| `templates.ts` | Template & CSS registration helpers |
| `streaming.ts` | NDJSON streaming reader + deferred state application |
| `actions.ts` | Form interception for mutation actions |
| `pending.ts` | Pending / error boundary UI state machine |
| `preload.ts` | Speculative prefetch on link hover |
| `loaders.ts` | Lazy component loading & route loader resolution |
| `route-element.ts` | `<webui-route>` DOM helpers (params, query, activate/deactivate) |

`router.ts` is now a thin orchestrator (~80 lines of imports + wiring)
that delegates all heavy lifting to these extracted modules.

### Server — `webui-handler` (Rust)

- **`ProtocolIndex`** — pre-computes component bit-index, compiled route
  cache (`CompiledRouteCache`), and per-fragment component closures once
  per protocol load instead of per-request.
- **`CompiledRouteCache`** — caches parsed route template patterns
  (`Vec<SegmentPattern>`) via `match_route_cached()`, eliminating
  per-request parsing allocations in the route-matching hot path.
- **`data-ri` attribute** — matched SSR routes now emit a chain index
  (`data-ri="N"`) so the client can bind routes in O(1) instead of
  DOM-walking.
- **`window.__webui` bootstrap object** — replaces scattered
  `<meta name="webui-inventory">` and `<script id="webui-chain">` tags
  with a single consolidated inline script containing `chain`,
  `inventory`, `nonce`, `css`, and `styles`.
- **`write_usize()`** — writes numeric `data-ri` values directly to the
  response writer, avoiding `format!` heap allocation.

### Other updates

- **`DESIGN.md`** — updated to reflect the new SSR bootstrap contract,
  `ProtocolIndex`, partial response fields (`allowedQuery`, `keepAlive`,
  `cacheControl`), and hydration flow.
- **`docs/guide/concepts/routing.md`** — updated user-facing routing docs.
- **`webui-framework`** — adjusted template/element APIs for the new
  registration flow.
- **Tests** — updated unit and E2E tests across router, handler, commerce
  example, and routes/todo examples.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mohamedmansour mohamedmansour requested a review from a team April 23, 2026 05:05
Comment thread packages/webui-test-support/src/register-template.ts Fixed
Comment thread packages/webui-test-support/src/register-template.ts Fixed
@mohamedmansour
Copy link
Copy Markdown
Contributor Author

@copilot resolve the conflicts, fetch origin main, and merge it, then resolve conflicts.

# Conflicts:
#	packages/webui-router/src/router.test.ts

Co-authored-by: mohamedmansour <68524+mohamedmansour@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 23, 2026

@copilot resolve the conflicts, fetch origin main, and merge it, then resolve conflicts.

Done. Fetched origin/main and merged it into chore/refactor-router (commit 6539aad).

The only manual conflict was in packages/webui-router/src/router.test.ts — the "fix flaky preload cache test" from main used the old storeCacheEntry/priv.cache API, while our refactored branch exposes NavigationCache.store(). Kept the HEAD version since our NavigationCache fully replaces the old API. All 261 Rust handler tests and 54 router unit tests pass after the merge.

- Wire process_outlet to CompiledRouteCache (ISSUE-004)
- Eliminate state double-serialization: use clone() instead of
  serialize→parse→re-serialize round-trip (ISSUE-005)
- Move const self/selfAction declarations before getter references
  to prevent TDZ crashes (ISSUE-007)
- Remove dead component_closure BFS computation from ProtocolIndex —
  field was computed but never read (ISSUE-009)
- Add state and templates fields to DESIGN.md window.__webui shape
  documentation (ISSUE-010)
- Add navGeneration guard to SSR initial navigation path to prevent
  stale state application after concurrent navigations (ISSUE-014)
- Add split_request_path + match_route_cached_with_segments to avoid
  per-iteration Vec allocation in route matching loops (ISSUE-020)
- Add self-initializing null guard to template IIFEs so they work
  even if window.__webui is not yet bootstrapped (ISSUE-023)
- Update hydration.md IIFE example to match actual parser output (ISSUE-028)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread packages/webui-test-support/src/register-template.ts Dismissed
Comment thread packages/webui-test-support/src/register-template.ts Dismissed
@mohamedmansour mohamedmansour requested a review from a team April 23, 2026 06:26
@mohamedmansour mohamedmansour merged commit 9916c93 into main Apr 23, 2026
21 checks passed
@mohamedmansour mohamedmansour deleted the chore/refactor-router branch April 23, 2026 06:27
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.

4 participants