react_server 0.1.0
react_server: ^0.1.0 copied to clipboard
Transport-neutral SSR and server-function primitives for React Dart.
react_server #
Transport-neutral SSR and server-function runtime for React Dart.
The package contains the server-function context and registry, the VM-side SSR worker client, and the Node-side React renderer. It has no Shelf or Routed dependency.
Installation #
dependencies:
react_server: ^0.1.0
Choose a separate HTTP adapter:
dependencies:
react_server_routed: ^0.1.0
# or
react_server_shelf: ^0.1.0
Server functions #
Create one registry and let generated code populate it:
import 'package:my_app/.generated/server_actions.g.dart';
import 'package:react_server/react_server.dart';
final actions = ServerFunctionRegistry();
void registerActions() {
registerServerActions(registry: actions);
}
Each handler receives a ServerFunctionContext containing request metadata,
authentication state, request headers, deadlines, and cancellation. Concrete
server adapters translate their request type into this context.
SSR worker client #
The Dart VM server communicates with the generated Node worker through
ReactSsrClient:
final ssr = ReactSsrClient(
endpoint: Uri.parse('http://127.0.0.1:3001/'),
);
final document = await ssr.render(
component: 'package:my_app/lib/app.dart#App',
props: {'title': 'Dashboard'},
);
ReactSsrDocument contains rendered HTML and serialized props. The HTTP
adapter injects both into the configured index template.
Caching and lifecycle primitives #
ReactDocumentCache is an in-process document cache. When documents must be
shared between processes or survive restarts, provide a ReactDocumentStore to
the selected HTTP adapter. The store receives the document TTL, stale-while-
revalidate window, and cache tags, so a Redis, database, disk, or edge-KV
implementation can preserve the same application contract.
For a single-host deployment, FileReactDocumentStore provides a restart-safe
JSON-on-disk implementation. ReactRouteManifest can supply route-specific
TTL, stale windows, and tags:
final app = ReactServerApp(
// ...
documentStore: FileReactDocumentStore(Directory('var/react-cache')),
routeManifest: ReactRouteManifest.fromJson({
'routes': [
{
'pattern': '/news/:slug',
'ttlSeconds': 30,
'staleWhileRevalidateSeconds': 300,
'tags': ['news'],
},
],
}),
);
Use a database, Redis, or edge-KV implementation of ReactDocumentStore when
the application runs on more than one host.
ReactDataCache provides typed data caching with concurrent-load
deduplication, stale-while-revalidate, and tag invalidation:
final data = ReactDataCache();
final user = await data.getOrLoad<User>(
'user:$id',
() => loadUser(id),
ttl: const Duration(minutes: 5),
tags: ['user:$id'],
);
Server functions can schedule non-critical work with
ServerFunctionContext.scheduleAfterResponse. The Routed and Shelf adapters
drain these callbacks after the action handler completes. Deployment-specific
durable background-work guarantees remain the responsibility of the host.
Partial prerendering #
Use ReactPartialDocument when a route has a cacheable shell and dynamic
regions with different lifetimes. The shell must contain a marker for each
region:
ReactPartialDocument(
shellKey: 'dashboard-shell',
shell: () => '<main><!--react-partial:summary--></main>',
regions: [
ReactPartialRegion(
key: 'summary',
ttl: const Duration(seconds: 15),
render: () => renderSummaryHtml(),
),
],
);
Pass the descriptor through partialDocument on ReactServerApp or
RoutedReactApplication. The adapters retain one ReactDataCache for the
application and resolve the shell and every region independently. A short
region TTL therefore does not invalidate the shell or unrelated regions.
Node renderer entrypoint #
The application's lib/ssr.dart is compiled to JavaScript. It imports hidden
generated factories and registries, registers component builders, and calls
registerGlobalRenderer. The generated Node runtime then invokes
renderToString inside a real React render stack, preserving hooks, contexts,
foreign components, suspense, refs, memoization, and error boundaries.
Package boundary #
- HTTP request/response handling belongs in
react_server_routedorreact_server_shelf. - Protocol annotations and browser clients belong in
react_actions. - Build and worker process orchestration belongs in
react_tool. - Test fixtures belong in
react_testingand compose with the selectedserver_testingadapter.