Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server-side Rendering (without hydration) #2335

Merged
merged 31 commits into from
Jan 12, 2022
Merged
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
65af3a2
Basic render to html implementation.
futursolo Jan 6, 2022
667796d
Remove HtmlWriter.
futursolo Jan 6, 2022
820d3ac
Escape html content.
futursolo Jan 6, 2022
1b2d823
Add non-suspense tests.
futursolo Jan 6, 2022
5b3f5e3
Add Suspense tests.
futursolo Jan 6, 2022
c7c9d2d
Gated "ssr" feature.
futursolo Jan 6, 2022
2bab219
Add example.
futursolo Jan 6, 2022
90deefc
merge master into ssr
futursolo Jan 6, 2022
482865e
Fix tests.
futursolo Jan 6, 2022
10f4ac4
Fix docs.
futursolo Jan 6, 2022
77b48c0
Fix heading size.
futursolo Jan 6, 2022
476300a
Remove the unused YewRenderer.
futursolo Jan 6, 2022
95e1d39
Remove extra comment.
futursolo Jan 6, 2022
655afd4
unify naming.
futursolo Jan 6, 2022
26bebb5
Update docs.
futursolo Jan 7, 2022
61f44d1
Update docs.
futursolo Jan 7, 2022
826b431
Update docs.
futursolo Jan 7, 2022
ed138b1
Isolate spawn_local.
futursolo Jan 7, 2022
bd26db4
Add doc flags.
futursolo Jan 7, 2022
f003aab
Add ssr feature to docs.
futursolo Jan 7, 2022
e56fcef
Move ServerRenderer into their own file.
futursolo Jan 7, 2022
ebe8c68
Fix docs.
futursolo Jan 7, 2022
10d7295
Update features and docs.
futursolo Jan 8, 2022
8635d63
Fix example.
futursolo Jan 8, 2022
3599240
Adjust comment position.
futursolo Jan 8, 2022
39a3d06
Fix effects being wrongly called when a component is suspended.
futursolo Jan 9, 2022
49566a0
Fix clippy.
futursolo Jan 9, 2022
17fd3b9
Uuid & no double boxing.
futursolo Jan 11, 2022
c67de39
merge master into ssr
futursolo Jan 11, 2022
0f24ae6
Merge branch 'master' into ssr
futursolo Jan 11, 2022
3567689
Merge branch 'master' into fursolo-ssr
ranile Jan 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update docs.
futursolo committed Jan 7, 2022
commit 26bebb53a208991d92137db1bf8e34ec717995f5
85 changes: 55 additions & 30 deletions website/docs/advanced-topics/server-side-rendering.md
Original file line number Diff line number Diff line change
@@ -5,31 +5,31 @@ description: "Render Yew on the server-side."

# Server-side Rendering

By default, Yew applications renders at the client side. That is, a skeleton
html file without any actual content and a WebAssembly bundle is
downloaded to the browser and everything is rendered at the client side.
This is known as client-side rendering.
By default, Yew applications render at the client side. When the viewer
visits a website, the server sends a skeleton html file without any actual
content and a WebAssembly bundle is downloaded to the browser.
Everything is then rendered at the client side by the WebAssembly
bundle. This is known as client-side rendering.

This approach works fine for most websites as most users now use a modern
browser and devices with adequate computing power.

However, there're some caveats with client-side rendering:
This approach works fine for most websites, with some caveats:

1. The user will not be able to see anything until the entire application is
downloaded and initial render has completed.
downloaded and initial render has completed. This can result in poor user
experience if the user is using a slow network and your application is
big.
2. Some search engines do not support dynamically rendered web content and
those who do usually rank dynamic websites lower in the search results.

To solve these problems, we can render our website on the server side.

## How it Works

Yew provides a `YewServerRenderer` renderer to render pages on the
Yew provides a `YewServerRenderer` to render pages on the
server-side.

You can create a render with `YewServerRenderer::<App>::new()`.
And calling `renderer.render().await` will render `<App />`
into a `String`.
To render Yew components at the server-side, you can create a renderer
with `YewServerRenderer::<App>::new()` and call `renderer.render().await`
to render `<App />` into a `String`.

```rust
use yew::prelude::*;
@@ -56,22 +56,29 @@ async fn main() {
The recommended way of working with server-side rendering is
function components.

All hooks other than `use_effect` will function normally until a component
successfully renders into `Html` for the first time.
All hooks other than `use_effect` (and `use_effect_with_deps`)
will function normally until a component successfully renders into `Html`
for the first time.

:::caution Web APIs are not available!

Web APIs such as `web_sys` are not available when using server-side rendering.
You application will panic if you try to use them.
You should isolate logics that need Web APIs in `use_effect` or
`use_effect_with_deps` as effects are not executed during server side
rendering.

:::caution
:::

:::danger

Whilst it's possible to use Struct Components with server-side rendering,
There's no clear boundaries between client-side safe logic like the
`use_effect` hook for struct components.
Struct Components will continue to accept messages until all of its
children is rendered and `destroy` method is called. Developers need to
there's no clear boundaries between client-side safe logic like the
`use_effect` hook for struct components and lifecycle events are invoked
in a different order than client side.

In addition, Struct Components will continue to accept messages until all of its
children are rendered and `destroy` method is called. Developers need to
make sure no messages possibly passed to components would link to logic
that makes use of Web APIs.

@@ -80,25 +87,43 @@ that makes use of Web APIs.
## Data Fetching during Server-side Rendering

Data fetching is one of the difficult point with server side rendering
and hydration. Traditionally, when the application renders, it is
instantly available. So there's no mechanism for Yew to detect whether
the application is still fetching. Hence, data client is responsible to implement
a custom solution to detect what's being requested during initial
rendering and triggers a second render after requests are fulfilled.
During the hydration process, the data clients also need to provide a way
to make the data fetched on the server-side available during hydration.
and hydration.

Traditionally, when a component renders, it is instantly available
(outputs a virtual dom to be rendered). This works fine when if the
component does not want to fetch any data. But what happens if the component
wants to fetch some data during rendering?

In the past, there's no mechanism for Yew to detect whether a component is still
fetching data or ready. The data fetching client is responsible to implement
a solution to detect what's being requested during initial render and triggers
a second render after requests are fulfilled. The server repeats this process until
no more pending requests are added during a render before returning a response.

Not only this wastes CPU resources by repeatedly rendering components,
but the data client also needs to provide a way to make the data fetched on
the server-side available during hydration process to make sure that the
the virtual dom returned by initial render is consistent with the
server-side rendered DOM tree which can be hard to implement.

Yew takes a different approach by trying to solve this issue with `<Suspense />`.

Suspense is a special component that when used on the client-side,
provides a way to show a fallback UI while the component is fetching
data (suspended) and resumes to normal UI when data fetching completes.
data (suspended) and resumes to normal UI when the data fetching completes.

When the application is rendered on the server-side, Yew waits until a
component is no longer suspended before serializing it to the string
component is no longer suspended before serializing it into the string
buffer.

Example: [simple\_ssr](https://github.com/yewstack/yew/tree/master/examples/suspense)
During the hydration process, elements within a `<Suspense /> component
remains dehydrated until all of its child components are no longer
suspended.

With this approach, developers can build a client-agnostic, SSR ready
application with data fetching with very little effort.

Example: [simple\_ssr](https://github.com/yewstack/yew/tree/master/examples/simple_ssr)

:::caution