mattkrick / cashay

:moneybag: Relay for the rest of us :moneybag:
MIT License
453 stars 28 forks source link

SSR Clarification #161

Closed padmaia closed 7 years ago

padmaia commented 7 years ago

The server-side rendering recipe uses ServerSideTransport, which no longer exists. I dug into the ParabolInc/action project to see how things are done there, and it looks like the cashay client is created with an empty transport so that it will always default to synchronously picking the default initial state in the client schema.

https://github.com/ParabolInc/action/blob/master/src/server/createSSR.js#L28

Does that sound right?

I think that's a reasonable approach since the main reasons for ssr are SEO and perceived speed, so sending down static data immediately and letting the client request dynamic data is a quick and simple win. But what if you wanted the flexibility? Do you plan on supporting the use case of being able to wait for asynchronous graphql data to come back before rendering to string?

Additionally, if this asynchronous data is unique per request, the fact that cashay is a singleton would cause issues. It seems like it would be relatively trivial to create a non singleton cashay client and pass it into some middleware. Middleware has access to dispatch and getState, which is all I see the client using, but I may have missed something. I know you may not feel it is worth doing, but do you see any potential pitfalls if it were something I wanted to look into?

Lastly, thanks for the great work on Cashay. Let me know if there are areas where I can contribute :)

mattkrick commented 7 years ago

hi @padmaia! Oooo i need to update that recipe it looks likes. Basically, a SSR transport is gonna be almost identical to any non-http transport (think websockets).

For example,

    const sendToServer = request => {
      return new Promise((resolve) => {
        socket.emit('graphql', request, (error, response) => {
          resolve(response);
        });
      });
    };
    const priorityTransport = new Transport(sendToServer);

Here is how I handle websockets. I'm just using the standard Transport class. If you wanted to handle SSR, then instead of the whole socket.emit you'd presumably hit up your graphql endpoint (or if you have a monolithic setup where graphql & rendering is handled by the same server, you could call the graphql function directly).

In my apps, I try to avoid hitting the DB for things that aren't behind a login wall. In doing so, serving up pages is much cheaper because i just let my CDN server up the same static content. If i absolutely have to serve up content from the DB, then i'll wait until the JS loads & then have the client fetch it. Given the choice, I'll always opt for dirt-cheap landing pages.

padmaia commented 7 years ago

If i absolutely have to serve up content from the DB, then i'll wait until the JS loads & then have the client fetch it. Given the choice, I'll always opt for dirt-cheap landing pages.

I figured. Sounds like the way to go, but I will have some convincing to do. Thanks!