leptos-rs / leptos

Build fast web applications with Rust.
https://leptos.dev
MIT License
15.97k stars 627 forks source link

Blocking resource with `SsrMode::PartiallyBlocked` doesn't work consistently #3048

Open spencewenski opened 5 days ago

spencewenski commented 5 days ago

Describe the bug SsrMode::PartiallyBlocked doesn't seem to block rendering as expected in 0.7 (main). Sometimes it works, but occasionally the suspense renders the fallback view instead.

Additionally, I noticed that the behavior is seems to be the same as when the default ssr mode is used.

Leptos Dependencies

Reproduced on main with some minor modifications to the hackernews_axum example (in this commit)

To Reproduce Steps to reproduce the behavior:

  1. Disable javascript in your browser
  2. Checkout my fork: git clone -b context-resource-startup https://github.com/spencewenski/leptos
  3. Run the hackernews_axum example
  4. Navigate to the example url (http://127.0.0.1:3000)
  5. Refresh the page a few times until only the Loading... fallback is displayed

Expected behavior The stories content should always be displayed instead of the Loading... fallback.

Screenshots 2024-09-29-182348_1026x943

Additional context Test on:

gbj commented 5 days ago

Oh at the moment the actual "partially blocked" behavior of replacing the fallback HTML inside the string is just a TODO, it is not yet implemented at all.

Note that in the large majority of cases SsrMode::Async or SsrMode::InOrder is preferable to PartiallyBlocked, and that PartiallyBlocked is only useful if you want a loading placeholder in one part of the page but you definitely don't want a loading placeholder in another part of the page. (For example, a blog post and comments.) In that case with JS disabled you will end up with a perpetual "Loading..." stuck somewhere anyway. In the hackernews app for example, SsrMode::Async is better than Resource::new_blocking() + SsrMode::PartiallyBlocked.

That said yes, it's in the todos.

gbj commented 5 days ago

Oh interesting, in fact I implemented this so long ago that I forgot about it, and in a relatively better way, such that the need for a separate PartiallyBlocked goes away entirely because it will work with regular OutOfOrder too. Fair enough.

I can't reproduce the issue on Actix which suggests to me immediately that it's a multi-threading issue (since Actix pins the whole request/response to a single thread and Axum does not.) Basically something is waking the stream back up to start sending chunks slightly before the chunk is actually ready. I imagine the cases where it sends the placeholder at the cases where Tokio has shifted it between threads, I'll have to take a look.