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

[SSR] Add and implement ToHtmlString trait for all virtual dom nodes #1154

Closed
jstarry opened this issue Apr 27, 2020 · 8 comments · Fixed by #2335
Closed

[SSR] Add and implement ToHtmlString trait for all virtual dom nodes #1154

jstarry opened this issue Apr 27, 2020 · 8 comments · Fixed by #2335
Labels
A-yew Area: The main yew crate feature-request A feature request

Comments

@jstarry
Copy link
Member

jstarry commented Apr 27, 2020

Is your feature request related to a problem? Please describe.
There is no way to convert yew virtual dom nodes (VNode variants) into html strings for use in server side rendering or static site generation

Describe the solution you'd like
Add and implement ToHtmlString trait for all virtual dom nodes

Additional context
Prior work: #874

@jstarry jstarry added feature-request A feature request blocked labels Apr 27, 2020
@teymour-aldridge
Copy link
Contributor

teymour-aldridge commented May 11, 2020

Could this also be used in testing Yew components?
e.g. you compare the output of ToHtmlString with your expected result

@chillcaw
Copy link

chillcaw commented Jun 9, 2020

Hey, I would be interested in picking this up. To my knowledge virtual_dom_rs is the only implementation that supports SSR right now. They have a virtual_dom_rs::VElement struct that is later used to create a web_sys::Element via virtual_dom_rs::VElement::create_element_node(). So effectively it looks like they have an intermediate representation of a Node without relying on web_sys. virtual_dom_rs doesn't have a ToHtmlString trait, but instead implements fmt::Display for their types in order to leverage ToString blanket implementation. Docs: https://docs.rs/virtual-dom-rs/0.6.14/virtual_dom_rs/struct.VElement.html

Would you be happy to implement something similar for yew? Or maybe a different VComp implementation behind ssr feature flag.

@jstarry
Copy link
Member Author

jstarry commented Jun 14, 2020

Hey @chillcaw!

Happy to hear about your interest in picking this up!

Or maybe a different VComp implementation behind ssr feature flag.

I'm definitely more in this camp. Basically everything we use web-sys for right now is not applicable to SSR. It will be tricky at times to untangle the rendering logic from Yew's virtual DOM implementation but I think it's worthwhile.

Happy to plan this out in more detail once you start diving in :)

@chillcaw
Copy link

I definitely agree with you there, I think this is worth the time investment. I am definitely looking forward to using Yew once this is supported.

I suppose there are a few ways of doing this. I guess the primary goal is to make VNode portable. We can either do this by decoupling VNode from web-sys entirely (Which is how virtual_dom_rs does it with their VirtualNode implementation), or we can have target checks for conditional compilation using #[cfg(not(target_arch = "wasm32"))] for a different VComp definition that doesn't rely on web_sys bindings for targets other than wasm32. I think using a feature flag might not be the way to do this, because the same code will need to be compiled both for wasm32 and for the server target in the same application.

One thing I'm unsure of is if we're able to check target_os or not, the only thing I've seen thus far is wasm32-unknown-unknown. I assume that target_arch = "wasm32" implies that Ecmascript Standard APIs exist.

A Rust SSR project might look like the following:

my-app/
    - public/
        - page-client.wasm
        - page-client2.wasm
        - index.html
    - page-component/ -> Crate can be compiled for all targets
    - page-component2/ -> Crate can be compiled for all targets
    - page-client/ -> Crate can be compiled to WASM, imports page-component
    - page-client2/ -> Crate can be compiled to WASM,  imports page-component2
    - my-server/ -> Crate can be compiled for server target
  1. Server will render our stringified page-component* onto an index.html
  2. /public/page-client*.wasm will be included in index.html
  3. Onload page-client*.wasm, it's mounted to a specified tag / id combination

I would be keen to hear your thoughts on the above. 😺

@jstarry
Copy link
Member Author

jstarry commented Jun 20, 2020

I think using a feature flag might not be the way to do this, because the same code will need to be compiled both for wasm32 and for the server target in the same application.

I think a feature flag would work well, could you elaborate more on why you think this might not work?

One thing I'm unsure of is if we're able to check target_os or not, the only thing I've seen thus far is wasm32-unknown-unknown. I assume that target_arch = "wasm32" implies that Ecmascript Standard APIs exist.

I think a check for target_arch is probably sufficient. This is what we use right now: https://github.com/yewstack/yew/blob/master/yew/Cargo.toml#L110

A Rust SSR project might look like the following:

Looks roughly like what I was imagining 👍 I'm a little afraid of devs having a hard time splitting page-client / page-component and needing config flags everywhere in page-component. But those issues are inevitable, looking forward to finding dev friendly solutions for them in the future!

@jstarry jstarry removed the blocked label Jun 20, 2020
@jstarry
Copy link
Member Author

jstarry commented Jun 20, 2020

Also, FYI this isn't blocked anymore. Getting the html string of a component node (VComp) should be pretty easy now

@Ciantic
Copy link

Ciantic commented Sep 8, 2020

It maybe "pretty easy now", but I can't figure out how do I convert even most simples example to a string:

let content = html! {
        <div class="thing">
        </div>
    };

(Trying to do a really simple static site generator.)

@mc1098 mc1098 added the A-yew Area: The main yew crate label Sep 20, 2021
@uglyluigi
Copy link

uglyluigi commented Sep 29, 2021

Also, FYI this isn't blocked anymore. Getting the html string of a component node (VComp) should be pretty easy now

It may be helpful to give an example. This is very crucial functionality that's pretty hard to track down in the docs between Yew and web_sys.

Edit: Now that I think about it, the Components documentation should probably add an example that includes creating a VComp or other VNode object -> converting to HTML -> putting it in the view. I can do it, except for converting the VNode object to an HTML string. Still haven't quite figured that out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-yew Area: The main yew crate feature-request A feature request
Projects
Status: History
6 participants