Git Product home page Git Product logo

Comments (9)

JoviDeCroock avatar JoviDeCroock commented on June 1, 2024 1

We have discussed supporting this internally quite a bit but on the team we aren't a 100% sure whether this is the best abstraction and we're on the lookout on what to support. Hence our current recommendation being preact-ssr-prepass.

Historically Pre React 18, the error you are describing happened in React as well, where react-ssr-prepass was introduced to counter-act this, after React 18 it just renders the Suspense fallback which imho isn't really ideal either 😅

My assumption is that streaming rendering will be the answer here as that could elegantly hook into these boundaries.

EDIT: documenting is a good shout, thank you!

from preact-render-to-string.

rschristian avatar rschristian commented on June 1, 2024 1

Is renderToString documented somewhere? I feel like I've missed something here.

It's the exact same thing as render, there's no difference. Just switched up the import name to avoid the conflict is all.

from preact-render-to-string.

rschristian avatar rschristian commented on June 1, 2024

The good news is that this is super simple to implement in user land.

Here's a (very slightly) modified excerpt from preact-iso/prerender inserted into your example showing how you could implement this:

import { renderToString } from "preact-render-to-string"
import { Main } from "./main"

const main = async () => {
    let tries = 0;
    const maxDepth = 10;
    const render = () => {
        if (++tries > maxDepth) return;
        try {
            return renderToString(<Main />);
        } catch (e) {
            if (e && e.then) return e.then(render);
            throw e;
        }
    };

    const rendered = await render();
    console.log(rendered)
}

from preact-render-to-string.

JoviDeCroock avatar JoviDeCroock commented on June 1, 2024

Alternatively you can use preact-ssr-prepass to do one pass that optimises parallel promises/... so first prepass and then renderToString

from preact-render-to-string.

aminnairi avatar aminnairi commented on June 1, 2024

The good news is that this is super simple to implement in user land.

Here's a (very slightly) modified excerpt from preact-iso/prerender inserted into your example showing how you could implement this:

import { renderToString } from "preact-render-to-string"
import { Main } from "./main"

const main = async () => {
    let tries = 0;
    const maxDepth = 10;
    const render = () => {
        if (++tries > maxDepth) return;
        try {
            return renderToString(<Main />);
        } catch (e) {
            if (e && e.then) return e.then(render);
            throw e;
        }
    };

    const rendered = await render();
    console.log(rendered)
}

Thank you for your reply, I'll try to create a reproduction of this fix in a separate branch to confirm that this is working and will push the updates to the repository I linked for the issue for people seeking answers like me.

Any reason why an error has been thrown, when this is not really an error but a promise? I'm really curious about the implementation details of this render function but I somewhat doubt I'll be able to understand any of this internal working.

Is renderToString documented somewhere? I feel like I've missed something here.

from preact-render-to-string.

aminnairi avatar aminnairi commented on June 1, 2024

Alternatively you can use preact-ssr-prepass to do one pass that optimises parallel promises/... so first prepass and then renderToString

Thank you for your reply.

Makes sense since when testing with a fully-fleged routing application I get this promise-error thingy the first time I try to render the page, and then it renders correctly on subsequent calls to the server.

But it is making Lighthouse crazy if you try to first-request your server with it.

I'll give preact-ssr-prepass a try if it means less implementation from the userland (what would be the ideal solution for me and maybe other non-power users).

from preact-render-to-string.

JoviDeCroock avatar JoviDeCroock commented on June 1, 2024

The way lazy and other Suspense mechanics work is basically throwing a Promise upwards at the point of async, this because VDOM is inherently boundary-based which means that if something within a boundary errors or can't render we need to throw so we can go up to the closest boundary to or react to the error or await the promise.

from preact-render-to-string.

aminnairi avatar aminnairi commented on June 1, 2024

The way lazy and other Suspense mechanics work is basically throwing a Promise upwards at the point of async, this because VDOM is inherently boundary-based which means that if something within a boundary errors or can't render we need to throw so we can go up to the closest boundary to or react to the error or await the promise.

Makes much sense now I see why, thank you very much for your insight!

Any reason why this is not done by default if this is the intended behavior behind Suspense & lazy? Or maybe is there some key differences in the implementation between react & preact for those component inside preact/compat?

from preact-render-to-string.

aminnairi avatar aminnairi commented on June 1, 2024

Alternatively you can use preact-ssr-prepass to do one pass that optimises parallel promises/... so first prepass and then renderToString

I can confirm that the preact-ssr-prepass package is working as intended, even with my own router when rendering on the server a VNode that has is lazy.

I feel like this can be (and should be) added in the documentation for people wanting to render asynchronous component (even with a custom implementation bound to this repository to not be dependant of any external libraries).

from preact-render-to-string.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.