en un clic
jaspr-pre-rendering-and-hydration
// Use when working in a **static** or **server** mode Jaspr project. Covers SSR/SSG, async data fetching, the @client annotation, hydration, and handling dual entrypoints (.server.dart vs .client.dart).
// Use when working in a **static** or **server** mode Jaspr project. Covers SSR/SSG, async data fetching, the @client annotation, hydration, and handling dual entrypoints (.server.dart vs .client.dart).
Use when you need to convert / rewrite existing HTML (from a file or url) into Jaspr code.
Use when working in a Jaspr project, on Jaspr components, or other Jaspr-related tasks. Contains fundamentals of writing Jaspr components and using HTML components.
Effectively integrate with Javascript when building Jaspr web applications. Use this skill when wrapping an existing JS library, accessing browser-native APIs, or bridging code safely across environments.
Write type-safe CSS-in-Dart to style Jaspr components. Use this skill when styling components, implementing themes, or using CSS properties.
| name | jaspr-pre-rendering-and-hydration |
| description | Use when working in a **static** or **server** mode Jaspr project. Covers SSR/SSG, async data fetching, the @client annotation, hydration, and handling dual entrypoints (.server.dart vs .client.dart). |
| metadata | {"jaspr_version":"0.23.1"} |
This skill is relevant for static and server mode Jaspr projects. You can check the mode of a Jaspr project in pubspec.yaml under jaspr: mode: <mode>.
Jaspr pre-renders components at request/build-time on the server. Interactive browser features require hydration.
lib/main.server.dart -> Calls runApp(Document(body: MyApp()))lib/main.client.dart -> Calls runApp(ClientApp())dart:js_interop or package:web in any code imported by the server entrypoint.dart:io or dart:ffi in any code imported by the client entrypoint.package:universal_web in shared code, but you MUST wrap any access to its browser APIs inside an if (kIsWeb) check to prevent crashing during server-side rendering.@client.@client Annotation and ClientAppWhen you annotate a component with @client, Jaspr renders its initial HTML on the server and "hydrates" it in the browser.
ClientApp() (called in the client entrypoint) automatically looks for and hydrates all @client components that were pre-rendered on the server.@client. Do not annotate child components in that subtree, they will automatically be hydrated as part of the parent.@client ComponentsUse parameters of @client components to pass data from the server to the client. These are automatically serialized on the server and deserialized in the browser.
const MyClientComponent({required this.title});).int, String, double, bool, List, Map) OR custom types that define @encoder and @decoder methods.
When pre-rendering in server or static mode, you often need to fetch data asynchronously (e.g., from a database or API) before rendering the HTML. Jaspr provides special server-only components to delay the build phase until the data is ready.
AsyncStatelessComponent or AsyncBuilder to perform async work during the build phase.package:jaspr/server.dart).@client component as a parameter if you need that data to be available for client-side interactivity.Example Usage:
import 'package:jaspr/server.dart'; // Note the server-only import!
import 'package:jaspr/dom.dart';
import 'my_interactive_button.dart';
// This component fetches data before server-rendering the HTML.
class MyServerComponent extends AsyncStatelessComponent {
const MyServerComponent();
@override
Future<Component> build(BuildContext context) async {
// 1. Fetch data asynchronously on the server
final databaseCount = await loadCountFromDatabase();
return div([
.text('This is static.'),
// 2. Pass the fetched data to the client component
MyInteractiveButton(initialCount: databaseCount),
]);
}
}
import 'package:jaspr/jaspr.dart';
import 'package:jaspr/dom.dart';
// This component runs in the browser (interactive).
@client
class MyInteractiveButton extends StatefulComponent {
const MyInteractiveButton({this.initialCount = 0});
final int initialCount;
@override
State<MyInteractiveButton> createState() => _MyInteractiveButtonState();
}
class _MyInteractiveButtonState extends State<MyInteractiveButton> {
late int count = component.initialCount;
@override
Component build(BuildContext context) {
return button(
onClick: () => setState(() => count++),
[.text('Clicked $count times')],
);
}
}