-
Notifications
You must be signed in to change notification settings - Fork 61
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
Render Dom-tree to string (SSR) #29
Comments
I've thought a lot about this, it's rather tricky because of the need to rehydrate the DOM. The server rendering part is easy, it can just render to a string, or use jsdom. The hard part is the client. The client needs to be able to find the existing DOM nodes and then attach events/signals to them. It's hard to do this correctly and efficiently. |
Good idea to run the wasm program in NodeJS instead of a real browser, I guess it should be faster and more robust!
Agree that would be hard. I was thinking to create the full dom tree again on the client-side, and then just replace the static rendering with it. |
The problem with that approach is that then there's not much benefit to the SSR: why spend all the time rendering the HTML, sending those HTML bytes to the browser, and having the browser render it if you're just going to throw it away? Search engines understand dynamic websites, so SEO isn't as much of a reason anymore. SSR adds an incredible amount of extra complexity (both on the server and client), so there would have to be a significant benefit to it. Being able to "pre-render" and rehydrate the DOM might be enough benefit to justify it. |
My impression for the main utility of SSR is for SEO benefits over raw performance benefits, for (only) the initial page load. |
@kylone My understanding is that search engines have supported dynamic pages (created by JS) for decades. So I'd like to see some evidence that static pages have better SEO than dynamic pages. |
In FRP context, I think prerender is needed, although I'm not sure for wasm. For example, in reflex-dom (haskell frp library), there is prerender functionality that might be similar. there is also documentation about what is prerendering. Maybe reflex is slightly different than dominator, but iirc, I use prerender when there is block of HTML that need to change based on certain event but we still need that block to be available while waiting for the event happened. |
@Rizary That sounds like pretty standard SSR. Unfortunately we can't use monads, because of our requirement to be zero-cost. So instead the solution will probably involve
I don't see what that has to do with prerendering, you can do that with regular signals: html!("div", {
.children_signal_vec(from_future(some_event()).map(|value| {
match value {
Some(value) => vec![render_app()],
None => vec![render_loading_screen()],
}
}).to_signal_vec())
}) This will wait for |
@Pauan thank you for the explanation, It seems that I have misunderstanding here. In reflex, the |
Here's a demo for rendering a rust-dominator app in NodeJS using jsdom: How it works
|
Hydration can be done pretty simply by wrapping a component in a browser web component and using connectedCallback to register and hydrate. But you still need to write a good hydration fn |
Yew supports SSR now, maybe a similar approach would make sense for dominator? |
@Boscop That's just standard SSR, so no I don't think it will work for dominator. There are a lot of things in dominator that make SSR difficult, in particular signals. A typical dominator app uses a lot of signals, but how will that work with SSR? There are two possibilities:
Both of these options have a lot of problems with them. Hydration is also a difficult topic, because signals can dynamically change the layout of the DOM. So what if you have some dominator code like this... html!("div", {
.child_signal(some_signal().map(|x| {
if x {
Some(html!("span", {}))
} else {
None
}
}))
}) On the server Things get tricky very fast whenever signals are involved, because the signals might not match between client and server. And the signals would have to somehow be synchronized between the client and server. And if we take the easy approach of just not running signals on the server, then that makes SSR completely pointless, because most dominator apps are going to use |
I was wondering how one could render a
Dom
-tree to an HTML string for server-side-rendering (SSR).Conceptually I see three options:
wasm-bindgen-test
. This should be quite easy to set up, but is slow and brittle. (example code)Dom
would not store aweb_sys::Node
but some internal struct, which could either contain a web_sys-node or some internal node representation.web_sys
at compile-time with a virtual dom library that has a compatible API toweb_sys
, and provides all the functionality needed by rust-dominator.What do you think about this topic in general? Are there other ways?
The text was updated successfully, but these errors were encountered: