Git Product home page Git Product logo

Comments (10)

lxsmnsyc avatar lxsmnsyc commented on June 7, 2024 1

But why does the browser even render the html page before it even has the whole picture, elements on the end of the document could change the whole page?

The whole concept of streaming is so that the browser can immediately show the page as early as possible. Streaming utilizes that fact and then sends the lazier chunks after it. Solid's async SSR is the complete opposite of this: it waits for everything before sending the entire HTML.

from solid-start.

lxsmnsyc avatar lxsmnsyc commented on June 7, 2024

It works as intended: the resource is called, triggering a Suspense boundary, where the resolving UI is streamed after the initial page load.

The only reason useAssets didn't work is because it's a server-only API and is never meant to be used isomorphically. And if we consider the SSR setting, the useAssets is called only after the fact that the initial html has been sent.

However, a probable solution here is to add deferStream: true to createResource, essentially turning it into a blocking resource rather than a streaming resource.

from solid-start.

BierDav avatar BierDav commented on June 7, 2024

Thanks for your answer, I understand that useAssets is only server-only, but that's quite inconvenient when useAssets doesn't work for ssr that is streamed. Is there a solution to this? Btw. what is actually streamed, the hydratable html or only the data?

And why doesn't useAssets work on the working page of my example, which should be completely rendered on the server without suspending:

<For each={data()}>
          {(coffee) => {
            useAssets(() => (
              <style>
                {`
                        #coffee-${coffee.id} {
                       width: 200px
                        }
                        `}
              </style>
            ));
            return <CoffeeItem coffee={coffee} />;
          }}
        </For>

But when it is a streaming resource why is the result directly in the initial response?

from solid-start.

lxsmnsyc avatar lxsmnsyc commented on June 7, 2024

Thanks for your answer, I understand that useAssets is only server-only, but that's quite inconvenient when useAssets doesn't work for ssr that is streamed. Is there a solution to this?

Like I mentioned, you add deferStream: true to the resource that you want to "await" before sending the initial HTML.

const [data] = createResource(fetchData, {
  deferStream: true,
});

return (
  <Suspense>
    <h1>{data()}</h1>
  </Suspense>
);

Btw. what is actually streamed, the hydratable html or only the data?

SSR sends first the initial HTML. If any Suspense boundary is triggered and the resource that triggered it is a streaming resource, the initial HTML only includes the fallback UI. When the resource resolves, the data is streamed to the client, alongside the "success" UI of the Suspense (this is the template element you are seeing).

And why doesn't useAssets work on the working page of my example, which should be completely rendered on the server without suspending:

If you're referring to the snippet combined with createResource, it still won't work, as it behaves in a similar way as your original repro. Point is once the resource resolves and Suspense tries to render the success UI, the initial HTML has already been sent, so there's no way to insert the new styles.

from solid-start.

BierDav avatar BierDav commented on June 7, 2024

When the resource resolves, the data is streamed to the client, alongside the "success" UI of the Suspense (this is the template element you are seeing).

Uhh ok that makes sense. But the point I wanted to make is that when the "success" UI is rendered on the server how should I be able to add styles inside the "success" UI, when I can't use useAssets, because the initial html is already sent and on the other hand the "success" UI is rendered on the server so I don't have access to the client.

Additionally what I don't understand is why not already inline the template when the "success" page is already available? I mean I can clearly see that in the template that is contained in the initial html the data is already filled in. I don't know if that was excatly the behaviour, but I would love to see a hybrid solution. So that all data that is responed before the initial html is sent is instantly inlined so that the user never sees the loading fallback and if the data fetching takes longer than ssr than we dynamically switch to streaming.

I cannot imagine that this is so difficult, because as pointed out the template where everything is there is included in the initial html. So clearly there must be some logic that optimizes that and adds the template immeditely without requireing to stream it. It just doesn't inline it.

Or is there a catch i didn't think of yet?

If you're referring to the snippet combined with createResource, it still won't work,

No I actually was referring to the snippet without createResource, which should in theory work, but it unfortunately doesn't

from solid-start.

lxsmnsyc avatar lxsmnsyc commented on June 7, 2024

Additionally what I don't understand is why not already inline the template when the "success" page is already available?

The thing is, it isn't. The same concept applies to how this doesn't work:

let example = 'Loading';

Promise.resolve().then(() => {
  example = 'Success';
});

console.log(example); // Loading

I mean I can clearly see that in the template that is contained in the initial html the data is already filled in. I don't know if that was excatly the behaviour, but I would love to see a hybrid solution

Browsers can batch chunks but the server doesn't know this and cannot make this kind of assumption.

I don't know if that was excatly the behaviour, but I would love to see a hybrid solution. So that all data that is responed before the initial html is sent is instantly inlined so that the user never sees the loading fallback and if the data fetching takes longer than ssr than we dynamically switch to streaming.

Which is what I recommended: deferStream: true

from solid-start.

BierDav avatar BierDav commented on June 7, 2024

Ok so tell me if I understood that correctly. Streaming means that the solid server renders everything until it hits a suspend boundary and immediately sends this to the browser, but it doesn't close the response stream. Instead it waits for all those resources and each time one finishes it renders it and emits a template in the response stream.

But why does the browser even render the html page before it even has the whole picture, elements on the end of the document could change the whole page?

Nevertheless, I know now what I want. I want a threshold that I can specify. Per default all resources should be evaluated deferred unless they take longer than the specified threshold (lets call it 300ms), after that period of time the server finishes rendering the rest and streaming the remaining resources when they have finished. This combines both worlds and optimizes layout shift and time to first byte.

Last but not least, I still need an alternative to useAssets so that we can push styles when streaming, this is a must have if we want to support streaming, because some conditional styles cannot be known ahead of time. Do you have any idea how I could solve that. With that knowledge I would make a pr to suid so that it also supports server side streaming or how this is called.

from solid-start.

BierDav avatar BierDav commented on June 7, 2024

Thanks for your detailed explanation. But what about useAssets in streaming mode?

from solid-start.

ryansolid avatar ryansolid commented on June 7, 2024

If you want the 0.3.10 async default you can just pass it in to createHandler. We default to streaming now but you can have the previous behavior.

createHandler(() => <StartServer />, { mode: "async" })

Streaming we've been using SolidMeta to do the split between assets that come from useAssets and adding them on the page in the client. We are looking at isomorphic handlers for assets that work seamlessly with streaming in Solid core. @lxsmnsyc has opened some PRs that I'm yet to review.

from solid-start.

BierDav avatar BierDav commented on June 7, 2024

Ahh thanks for your info, the thing with the async mode I have also already found out, but thanks for making it clear.

I will close the issue now, because everything is clear now and this has been more a discussion than an issue.

Have a nice day, @lxsmnsyc and @ryansolid

from solid-start.

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.