vikejs / vike-solid

🔨 Solid integration for Vike
https://vike.dev/vike-solid
MIT License
33 stars 4 forks source link

Progressive Rendering #95

Open brillout opened 3 weeks ago

brillout commented 3 weeks ago

React 18 introduced Progressive Rendering. Does Solid support this?

It would be nice to potentially integrate it with Vike extensions (e.g. https://github.com/vikejs/vike-solid/issues/94 and the upcoming vike-{react,vue,solid}-telefunc).

phonzammi commented 1 week ago

Hi @brillout

I've been trying out some examples using vike-solid, solidjs, and solid-start, as well as combinations like vike-solid with solid query and solidjs with solid query. @ryansolid, allow me to tag you here.

Here are my conclusions:

  1. vike-solid, repo: vike-solid-streaming-ssr-test, codesandbox.
vike-solid-streaming-ssr-test-1 vike-solid-streaming-ssr-test-2

From the video vike-solid-streaming-ssr-test-1, we can see that while the page is streaming and the content is still loading, clicking the counter button doesn't trigger interaction. However, after the content fully loads and displays, the counter updates based on previous clicks. If I recall correctly, @ryansolid referred to this as event replay.

Also, from the console's network tab, we can observe that something is preventing all assets from being fetched until the movies are fetched. I'm not sure what is causing this issue. (This also occurs even when using solid-query).

From the video vike-solid-streaming-ssr-test-2, when I changed the script tag to be HTML_BEGIN (which means that vike_pageContext script, the viteDevScript, and the client entry script will be inserted inside the <head> tag), there is no more blocking, the counter is interactive while streaming the content. But after the movies are fetched on the server and the Loading suspense disappears, the movies are being fetch again in the browser. This issue only happens if we click the counter while the content is still loading. @ryansolid, do you know what causing this issue? I may need to create a separate issue on the solid's repo since this issue also happened on the solidjs & solid-start side.

  1. vike-solid with solid-query. vike-solid-streaming-ssr-test-with-react-query.

Using solid-query with all those scripts tag inserted to the <head> we finally accomplished what we wanted.

  1. solidjs: solid-streaming-ssr-test, solid-start : solid-start-streaming-ssr-test, and solidjs + solid-query : solid-query-streaming-ssr-test.
solidjs solid-start solidjs + solid-query

That's all I have for now. I hope that helps. Please take a look, review it, and correct me where I'm wrong.

brillout commented 1 week ago

Thank you phonzammi for the nice digging :100:

FYI there is some dependency injection going on between Vike and react-streaming which enables Vike to inject into React's SSR stream. (In Vike internal technical terms: STREAM instead of HTML_END.) We could do the same for Solid. Does Solid provide a primitive to inject into the SSR stream (something like https://github.com/reactjs/rfcs/pull/219)?

As for the double fetching issue, I guess the question here is whether it's a bug on Solid's side or on Solid Start's side?

phonzammi commented 1 week ago

Does Solid provide a primitive to inject into the SSR stream (something like reactjs/rfcs#219)?

AFAIK, it doesn't. But, solidjs does have onCompleteShell & onCompleteAll options that we can use like this :

pageView = renderToStream(() => getPageElement(pageContext), {
        onCompleteShell(info) {
            info.write("<script></script>")
        },
      }).pipe;

After doing more research, here is the sequence of how Vike + Solid streams when there is an async component (like in this test):

  1. fetchMovies start
  2. injectStringAtBegin()
  3. first stream (non promise string: from layout to Loading placeholder or template tag and a bit of <script> tag)
  4. onCompleteShell()
  5. fetchMovies done
  6. second stream : <template> tag included all movies list
  7. third stream : Long <script> tag to replace Loading template with Movies list.
  8. onCompleteAll()
  9. injectStringAtEnd()

Due to injectStringAtEnd(), which also injects a client entry script, being executed at the very end, hydration does not occur until everything is finished. I may have an idea on how we can inject the vike_pageContext script, viteDevScript, and the client entry script after the first stream is flushed. I'll try to create a PR on Vike's core once I've done it.

As for the double-fetching issue, which is indeed a limitation on the SolidJS side (https://github.com/solidjs/solid/issues/2217), let's hope that it can be resolved.