You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Summary
This PR adds first-class hydration islands to `@lazarv/react-server`
through a new inline `"use hydrate"` directive. A component marked with
this directive is rendered as normal server HTML during the initial
response, but its interactive React tree is isolated into island-scoped
hydration data and hydrated later as a local non-root outlet. This
allows mostly static pages to keep the page root unhydrated while
selected subtrees become interactive according to an explicit strategy.
## Implementation
The directive transform extracts `"use hydrate"` components in the same
style as the existing inline directive pipeline and rewrites them to an
internal hydration island component. On the server, the island renderer
produces the initial HTML and a separate RSC payload for the island. In
rootless pages, the client entry detects island markers and hydrates
each island with `hydrateRoot`. On pages that already have a
`PAGE_ROOT`, the island is represented by a client boundary inside the
existing React tree; that boundary reads request-scoped hydration data,
waits for the selected strategy when needed, and then renders a
`ReactServerComponent` for the island outlet without creating another
root.
The island runtime supports `load`, `idle`, `visible`, `interaction`,
`media`, and `never` strategies. Deferred strategies can delay both
hydration and client module loading, and the manifest collection path
now skips initial modulepreload entries for client modules that are only
imported by deferred hydration island modules. When a `"use hydrate"`
component appears later inside an RSC navigation or update payload, it
intentionally renders as plain component output instead of creating a
new island, because that subtree is already owned by the existing React
tree.
Hydration islands are registered as local outlets, so hydrated islands
can use local `Link` navigation and `Refresh` without navigating or
hydrating the page root. DevTools now identifies these outlets as
islands rather than remotes and exposes their hydration state so
pending, scheduled, hydrating, and hydrated islands are visible in the
outlets panel.
## Documentation and Example
The docs add a new Hydration Islands feature page that explains how
islands differ from client components and PPR, documents each hydration
strategy, and describes local outlet navigation, browser history
behavior, and DevTools support. The comparison page was updated to
reflect hydration islands, HTTP/runtime capabilities, observability,
server function defenses, and server function middleware tradeoffs
across React Server, Next.js, TanStack Start, React Router, Waku, and
Astro where relevant. The LLM reference and React Server skill were also
updated so agents know about the new directive and rendering model.
A new `examples/hydration-islands` app demonstrates rootless hydration
islands, mixed `PAGE_ROOT` mode, every supported strategy, visible
client-component loading, RSC refresh, and local outlet navigation
through `Link`.
Copy file name to clipboardExpand all lines: docs/public/llms.txt
+2Lines changed: 2 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -32,6 +32,7 @@ No config files, no boilerplate, no separate React installation needed. Or use t
32
32
33
33
- **React Server Components**: The default rendering model. Components render on the server, support async/await, and their source code never reaches the client.
34
34
- **Client Components**: Add `"use client"` directive to enable interactivity. Components are server-rendered then hydrated on the client.
35
+
- **Hydration Islands**: Add `"use hydrate"` inside a server component function to render that subtree as HTML immediately and hydrate it later as a local non-root outlet. Strategies are `load`, `idle`, `visible`, `interaction`, `media`, and `never`. If rendered in a later RSC update payload, it returns normal React content instead of creating a new island.
35
36
- **Server Functions**: Add `"use server"` to turn async functions into server-side RPC endpoints. Works as form actions with progressive enhancement.
36
37
- **Typed Router**: Fully typed routing with `createRoute` and `createRouter`. Compile-time type safety for route paths, params, and search params. Schema validation with Zod, ArkType, Valibot, or lightweight parse functions. Typed `Link` components, typed hooks, typed programmatic navigation.
37
38
- **File-System Router**: Activates automatically when no entrypoint is specified. Supports pages, layouts, outlets, API routes, middlewares, error boundaries, loading states, client-only routes, route validation, and auto-generated typed route descriptors via `@lazarv/react-server/routes`.
@@ -66,6 +67,7 @@ No config files, no boilerplate, no separate React installation needed. Or use t
66
67
- [Middleware Mode](https://react-server.dev/features/middleware-mode): Running @lazarv/react-server as middleware inside existing servers like Express or NestJS in both dev and production
67
68
- [Cluster Mode](https://react-server.dev/features/cluster): Running the production server in multi-process cluster mode to utilize all CPU cores
68
69
- [Partial Pre-Rendering](https://react-server.dev/features/ppr): Pre-rendering static shells at build time while deferring dynamic content to runtime using "use dynamic" and "use static" directives
70
+
- [Hydration Islands](https://react-server.dev/features/hydration-islands): Server-rendered subtrees marked with "use hydrate" that hydrate later as local non-root outlets without requiring PAGE_ROOT hydration; supports load, idle, visible, interaction, media, and never strategies; later RSC update payloads render them as normal React content
69
71
- [Live Components](https://react-server.dev/features/live-components): Real-time streaming components using the "use live" directive with async generator functions pushing updates over WebSocket
70
72
- [Workers](https://react-server.dev/features/worker): Offloading heavy computations to separate threads using "use worker" with RSC-based serialization — Node.js Worker Threads on server, Web Workers on client
71
73
- [Micro-Frontends](https://react-server.dev/features/micro-frontends): Implementing micro-frontend architecture with RemoteComponent for loading and rendering remote React applications with SSR
`@lazarv/react-server` is a full React Server Components runtime — not just a router. The routing system is deeply integrated with RSC streaming, server functions, and the Vite build pipeline. This means features like typed routes, client-only routes, and server-side validation work end-to-end without glue code.
170
174
175
+
<Linkname="key-architectural-differences">
171
176
### Key architectural differences
177
+
</Link>
178
+
179
+
<Linkname="rsc-native-runtime">
180
+
#### RSC-native runtime
181
+
</Link>
182
+
183
+
Unlike routers that bolt RSC support on top, `@lazarv/react-server` was built from the ground up for React Server Components. Every route can mix server and client components freely.
184
+
185
+
<Linkname="production-http-runtime">
186
+
#### Production HTTP runtime
187
+
</Link>
188
+
189
+
`@lazarv/react-server` ships a production runtime with keep-alive and timeout tuning, admission control, adaptive ELU-based backpressure, request/body and multipart limits, CSRF origin validation for action POSTs, health/readiness endpoints, and graceful shutdown. In many other React stacks, these concerns are delegated to the hosting platform, custom server, reverse proxy, or adapter rather than exposed as a first-class runtime layer.
190
+
191
+
<Linkname="server-function-defense-layer">
192
+
#### Server function defense layer
193
+
</Link>
194
+
195
+
`@lazarv/react-server` treats server function invocation as hostile input before application code runs. Server function references are encrypted with AES-256-GCM capability tokens, support key rotation, and are decoded through configurable resource ceilings (`maxRows`, `maxDepth`, `maxBytes`, string/BigInt/stream limits) plus structural defenses against prototype pollution, forbidden path walks, hostile thenables, and forged callables. Next.js has meaningful Server Action defenses such as secure IDs, origin checks, closure encryption, and a body-size cap; TanStack Start has CSRF middleware and validators. The distinctive `react-server` behavior is the combined capability-token and hardened RSC reply-decoder layer as a first-class runtime boundary.
196
+
197
+
<Linkname="server-function-middleware-model">
198
+
#### Server function middleware model
199
+
</Link>
200
+
201
+
TanStack Start has the most direct server-function middleware model in this comparison: function middleware can wrap server functions with client-side logic, server-side logic, input validation, composition, and global registration. `@lazarv/react-server` does not currently expose a first-class TanStack-style per-function middleware chain. Its request middleware runs before server function dispatch and can short-circuit or annotate the request, while `createFunction` provides protocol-level per-argument parse/validate contracts before the handler runs. Cross-cutting per-function policy can still be composed with userland wrappers, but the first-class runtime primitive is the request middleware plus contract/decoder boundary, not a client/server function middleware pipeline. React Router middleware wraps route `action`/`loader` requests, which is useful but tied to the route action model rather than arbitrary RPC server functions, so it is also not first-class support for this specific row.
202
+
203
+
<Linkname="observability-runtime">
204
+
#### Observability runtime
205
+
</Link>
206
+
207
+
`@lazarv/react-server` has built-in OpenTelemetry integration that can automatically instrument HTTP requests, middleware, RSC/SSR rendering, server functions, cache lookups, server startup, and Vite dev hooks, plus built-in request, render, server function, and cache metrics. Telemetry dependencies are optional and lazy-loaded, so disabled telemetry resolves to no-op instrumentation. Next.js also has official OpenTelemetry instrumentation and framework spans. React Router exposes first-class instrumentation wrappers that apps wire into logging or tracing. TanStack Start documents observability patterns and manual/experimental OpenTelemetry setup, while Waku leaves this mostly to userland or the host platform.
208
+
209
+
<Linkname="client-only-routes">
210
+
#### Client-only routes
211
+
</Link>
212
+
213
+
Pages with `"use client"` in the file-system router are automatically client-only — navigation skips the server entirely. No configuration needed, and component state is preserved across navigations via React's `<Activity>` component.
214
+
215
+
<Linkname="schema-agnostic-validation">
216
+
#### Schema-agnostic validation
217
+
</Link>
218
+
219
+
Route params and search params can be validated with any schema library (Zod, ArkType, Valibot) or lightweight parse functions — the runtime detects the validation strategy automatically.
220
+
221
+
<Linkname="rsc-typed-resources">
222
+
#### RSC + typed resources
223
+
</Link>
224
+
225
+
`@lazarv/react-server` offers two complementary data-fetching approaches: React Server Components with `async/await` (RSC as loaders), and **typed resources** — schema-validated, reference-identified data descriptors with `.use()` (suspense), `.query()` (imperative), `.prefetch()`, and `.invalidate()`. Resources use `"use cache"` as the caching runtime — no custom cache layer, no SWR boilerplate. Route-resource bindings enable parallel prefetching on navigation.
226
+
227
+
<Linkname="route-level-dependencies">
228
+
#### Route-level dependencies
229
+
</Link>
230
+
231
+
TanStack Router exposes route context as a first-class typed primitive for passing dependencies (auth, DB clients, etc.) down the route tree. `@lazarv/react-server` models the same problem space through typed resources, request context, and native modules — there is no separate route-context bag because resources already carry schema-validated, route-scoped data with full type safety.
232
+
233
+
<Linkname="built-in-devtools">
234
+
#### Built-in devtools
235
+
</Link>
236
+
237
+
`@lazarv/react-server` ships with integrated devtools (`--devtools`) that go beyond route inspection — they cover RSC payload, cache entries, routes, outlets, remote components, live components, workers, and server logs in a single panel. TanStack Router provides excellent router-focused devtools, but `@lazarv/react-server`'s devtools cover the full server component runtime.
238
+
239
+
<Linkname="outlets-vs-parallel-routes">
240
+
#### Outlets vs. parallel routes
241
+
</Link>
242
+
243
+
`@lazarv/react-server` uses named outlets (`@sidebar`, `@content`) rendered as typed props to layouts. This is functionally similar to Next.js parallel routes but with stronger typing — each outlet is a branded React element that prevents accidentally swapping outlets.
244
+
245
+
<Linkname="route-identity-over-masking">
246
+
#### Route identity over route masking
247
+
</Link>
248
+
249
+
`@lazarv/react-server` intentionally does not support TanStack-style route masking. The visible browser URL, server request URL, matched route tree, RSC payload, route validation, resources, cache keys, outlets, and devtools state are expected to describe the same navigation state. Use rewrites, redirects, route groups, outlets, or search params when a URL needs a different presentation, without creating hidden client-only route identity.
250
+
251
+
<Linkname="route-lifecycle-model">
252
+
#### Route lifecycle model
253
+
</Link>
254
+
255
+
`@lazarv/react-server` exposes navigation guards (`useNavigationGuard`, `registerNavigationGuard`) for client-side page-root navigation decisions, including back/forward and optional `beforeUnload` handling. Internally, route guard/registration components manage route registration, active visibility, route resources, loading skeletons, and `Activity`-based preservation. User effects should live in React effects, resources, middleware, server functions, or cache invalidation rather than router-object mount/unmount callbacks.
`@lazarv/react-server` hydration islands are initial-rendering boundaries that render server HTML immediately, store request-scoped island hydration data, and later hydrate as independent local outlets. This can work without a hydrated `PAGE_ROOT`. TanStack Start has deferred hydration-style behavior for suspended React subtrees, but that subtree still lives inside the page's React tree rather than becoming a separate island outlet with its own RSC payload. Astro is the closest architectural match outside this React/RSC comparison: it has a real island architecture for component-level hydration, but it is not an RSC local-outlet model. Other React frameworks can lazy-load client components or defer JavaScript in userland, but they do not provide this local-outlet island model as a first-class feature.
262
+
263
+
<Linkname="waku-minimal-rsc">
264
+
#### Waku
265
+
</Link>
172
266
173
-
-**RSC-native**: Unlike routers that bolt RSC support on top, `@lazarv/react-server` was built from the ground up for React Server Components. Every route can mix server and client components freely.
174
-
-**Client-only routes**: Pages with `"use client"` in the file-system router are automatically client-only — navigation skips the server entirely. No configuration needed, and component state is preserved across navigations via React's `<Activity>` component.
175
-
-**Schema-agnostic validation**: Route params and search params can be validated with any schema library (Zod, ArkType, Valibot) or lightweight parse functions — the runtime detects the validation strategy automatically.
176
-
-**RSC + typed resources**: `@lazarv/react-server` offers two complementary data-fetching approaches: React Server Components with `async/await` (RSC as loaders), and **typed resources** — schema-validated, reference-identified data descriptors with `.use()` (suspense), `.query()` (imperative), `.prefetch()`, and `.invalidate()`. Resources use `"use cache"` as the caching runtime — no custom cache layer, no SWR boilerplate. Route-resource bindings enable parallel prefetching on navigation.
177
-
-**Route-level dependencies**: TanStack Router exposes route context as a first-class typed primitive for passing dependencies (auth, DB clients, etc.) down the route tree. `@lazarv/react-server` models the same problem space through typed resources, request context, and native modules — there is no separate route-context bag because resources already carry schema-validated, route-scoped data with full type safety.
178
-
-**Built-in devtools**: `@lazarv/react-server` ships with integrated devtools (`--devtools`) that go beyond route inspection — they cover RSC payload, cache entries, routes, outlets, remote components, live components, workers, and server logs in a single panel. TanStack Router provides excellent router-focused devtools, but `@lazarv/react-server`'s devtools cover the full server component runtime.
179
-
-**Outlets vs. parallel routes**: `@lazarv/react-server` uses named outlets (`@sidebar`, `@content`) rendered as typed props to layouts. This is functionally similar to Next.js parallel routes but with stronger typing — each outlet is a branded React element that prevents accidentally swapping outlets.
180
-
-**Waku**: Waku is another RSC-native framework built on Vite, but takes a deliberately minimal approach. It provides basic file-based routing with layouts and RSC support, but lacks the typed routing system, search param handling, scroll restoration, middleware, and most advanced routing features. Waku's `Link` component supports basic `scroll` and `prefetchOnEnter`/`prefetchOnView` props, but most of its router API is still marked as `unstable_`. Waku is a good choice for simple RSC applications that don't need advanced routing.
267
+
Waku is another RSC-native framework built on Vite, but takes a deliberately minimal approach. It provides basic file-based routing with layouts and RSC support, but lacks the typed routing system, search param handling, scroll restoration, middleware, and most advanced routing features. Waku's `Link` component supports basic `scroll` and `prefetchOnEnter`/`prefetchOnView` props, but most of its router API is still marked as `unstable_`. Waku is a good choice for simple RSC applications that don't need advanced routing.
Copy file name to clipboardExpand all lines: docs/src/pages/en/(pages)/features/devtools.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -253,7 +253,7 @@ The Outlets tab lists every named outlet currently rendered on the page. Outlets
253
253
|-------|---------|
254
254
| Name | The outlet identifier |
255
255
| URL | The URL the outlet content was loaded from (if applicable) |
256
-
| Badge | How the outlet is managed: `router` (file-router), `remote` (fetched from another server), `live` (streaming), `defer` (lazily loaded), or `static`|
256
+
| Badge | How the outlet is managed: `router` (file-router), `remote` (fetched from another server), `island` (hydration island), `live` (streaming), `defer` (lazily loaded), or `static`. Hydration islands also show `hydrated` or `not hydrated` so you can see whether the island has already become interactive.|
0 commit comments