vike-solid icon indicating copy to clipboard operation
vike-solid copied to clipboard

Progressive Rendering

Open brillout opened this issue 1 year ago • 8 comments

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).

brillout avatar Jun 24 '24 05:06 brillout

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.

phonzammi avatar Jul 07 '24 10:07 phonzammi

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?

brillout avatar Jul 07 '24 10:07 brillout

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.

phonzammi avatar Jul 10 '24 09:07 phonzammi

Hi @brillout and @magne4000

I’ve updated a working example : vike-solid-streaming-ssr-example.

Note about issue https://github.com/solidjs/solid/issues/2217: My previous test with SolidJS (without Solid Query) used a different approach compared to using SolidJS with Solid Query. AFAIK, the issue is just with where we use the <Suspense> component. My apologies for the confusion; it was my mistake. I actually implemented it correctly with Solid Query and didn’t notice the difference. :man_facepalming:

Please take a look and let me know if it’s good enough and if it’s the right approach.

See also : https://github.com/solidjs/solid/issues/2217#issuecomment-2303610725

phonzammi avatar Aug 22 '24 14:08 phonzammi

I’ve updated a working example : vike-solid-streaming-ssr-example.

I've tried this example (including with solid-query) using vike-solid from @0.7.0, to @0.7.3, and the result is interesting. Progressive rendering works in development mode but not in preview. However, using [email protected] works for both.

Do you have any idea what changes could be causing this issue?

phonzammi avatar Aug 28 '24 16:08 phonzammi

what changes could be causing this issue?

I tried again by commenting out this line, https://github.com/vikejs/vike-solid/blob/98fe78fc3494054cf47597925d8f7af47ad3094e/vike-solid/renderer/onRenderHtml.tsx#L92 and progressive rendering now works in preview mode.

Update : Either remove https://github.com/vikejs/vike-solid/blob/98fe78fc3494054cf47597925d8f7af47ad3094e/vike-solid/renderer/onRenderHtml.tsx#L91 or https://github.com/vikejs/vike-solid/blob/98fe78fc3494054cf47597925d8f7af47ad3094e/vike-solid/renderer/onRenderHtml.tsx#L92 makes progressive rendering works in preview mode.

phonzammi avatar Aug 29 '24 02:08 phonzammi

That seems surprising? Is that a Solid bug or quirk?

brillout avatar Aug 30 '24 08:08 brillout

After further investigation and testing with the vike-solid-streaming-ssr-example/with-express using Express, including adding several dummy meta tags, I believe the issue lies with the Vite preview server.

We encounter the same issue with vike-react.

Update : After digging a bit deeper, I found that Vite uses the @polka/compression middleware on the preview server.

I also tried using @polka/compression with Express: https://github.com/phonzammi/vike-solid-streaming-ssr-example/commit/ce75a06768c38d0c6b618b7ef23e3f3c6bb63d9e, and the result was the same as with the Vite preview server: it breaks Progressive Rendering.

phonzammi avatar Sep 05 '24 17:09 phonzammi