π Run your App
To run your app, use the runApp
function and provide your root component.
runApp(MyComponent());
This function is not available under the normal package:jaspr/jaspr.dart
import. Instead, you
must use the platform-specific package:jaspr/browser.dart
or package:jaspr/server.dart
import
in your web and server entrypoint, respectively.
We have separate imports since the runApp
method works slightly different depending on whether
we are on the server or client.
-
On the server this starts a http server that renders the given component to html for every incoming request.
-
On the client this attaches the given component to the DOM and thereby making your app interactive.
Let's look at a simple example on how this works in practice. A minimal file structure looks like this:
βββ lib/
β βββ app.dart
β βββ main.dart
βββ web/
βββ main.dart
This consists of
-
an
lib/app.dart
with anApp
component that we want to use both for server-side rendering and client-side hydration, -
a
lib/main.dart
file that is the entrypoint on the server for our app// Server-specific import import 'package:jaspr/server.dart'; // Our main component import 'app.dart'; void main() { // Starts the server and renders the app component runApp( // Special component that sets up the main document tags // like <html>, <head>, and <body>. // More on this later Document( // Links to the `web/main.dart` file. scriptName: 'main', // Renders the component inside the <body> tag body: App(), ), ); }
-
a
web/main.dart
file that is the entrypoint on the client for our app// Client-specific import import 'package:jaspr/browser.dart'; // Our main component import 'lib/app.dart'; void main() { // Attaches the app component to the <body> tag // and hydrates the component / makes it interactive. runApp(App(), attachTo: 'body'); }
It is important that you attach your component on the client to the same location in the tree where you rendered it on the server. This does not need to be <body>, but must be the same.
π The Document
The Document
component helps you to set up a basic document structure at the root of your app.
It renders the main <html>
, <head>
and <body>
tags and takes a set of standard parameters,
e.g. to set the title
or meta
attributes inside the <head>
.
The Document
component can only be used on the server and is therefore also only available using the
package:jaspr/server.dart
import.
The standard Document
constructor takes the following arguments:
String? title
: Sets the title of your website.String? base
: Sets the<base>
tag of your website.String? charset
: Sets the charset, defaults to 'utf-8'.String? viewport
: Sets the viewport for mobile devices, defaults to 'width=device-width, initial-scale=1.0'.Map<String, String>? meta
: Sets additional<meta>
properties.List<StyleRule>? styles
: A global set of style-rules, rendered as a<style>
section inside<head>
.String? scriptName
: The name of the script that corresponds to your web entrypoint, e.g.main
forweb/main.dart
.List<Component> head
: Additional components to render inside<head>
.Component body
: The component to render inside<body>
.
There are also one other constructors that you can use instead:
-
Document.file() where you can use an external html file that defines the document markup.
See the
classic
template for an example setup.
βClient Components
With the previous approach you have to set up and link the entrypoints for the client manually.
However, jaspr can also do that for you using the @client
annotation.
Annotate a component that you want to be shipped and hydrated on the client with @client
like this:
import 'package:jaspr/jaspr.dart';
// will be generated by jaspr
part 'app.g.dart';
// marks this as a client component
@client
class App extends StatelessComponent with _$App {
@override
Iterable<Component> build(BuildContext context) sync* {
yield ...;
}
}
When you use the @client annotation, your web entrypoints will be automatically generated and used in your
server-rendered markup. Therefore, you don't need to have a web/main.dart
file and don't need to set Document.scriptName
.
Using this component in your server-rendered application anywhere in the tree under Document()
will
automatically set up this component also on the client.
You can also have multiple components annotated with @client
to have separate interactive 'islands' on the client.
However, nesting client components is currently not possible.