refactor(router): decompose monolithic router into single-responsibility modules#268
Merged
mohamedmansour merged 3 commits intomainfrom Apr 23, 2026
Merged
refactor(router): decompose monolithic router into single-responsibility modules#268mohamedmansour merged 3 commits intomainfrom
mohamedmansour merged 3 commits intomainfrom
Conversation
…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>
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>
Contributor
Done. Fetched The only manual conflict was in |
- 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>
akroshg
approved these changes
Apr 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Broke the ~1,800-line monolith
router.tsinto 8 focused modules and optimized the Rust-side route handler for faster SSR rendering.Client —
webui-routercache.tsNavigationCache— LRU eviction + tag-based invalidationrouter.tsis 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>) viamatch_route_cached(), eliminating per-request parsing allocations in the route-matching hot path.data-riattribute — 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.__webuibootstrap object — replaces scattered<meta name="webui-inventory">and<script id="webui-chain">tags with a single consolidated inline script containingchain,inventory,nonce,css, andstyles.write_usize()— writes numericdata-rivalues directly to the response writer, avoidingformat!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.