Skip to content

Server Rendering for Queries? #501

Description

@curran

Greetings,

Is it possible to execute a ShareDB Query server-side, then pass the results data into the client via server rendering and use that to data hydrate a client-side ShareDB query?

Use case: a page that lists a number of ShareDB documents, where server rendering is in play.

Desired behavior: the query runs against the database once during server rendering, then in the client side the same query can be instantiated with results from the first execution, then subscribed for updates without triggering the query to be executed again.

I notice there is an internal method on Queries called _ingestSnapshots. This seems useful for the task at hand.

Is it possible to leverage that method? Might it be possible to expose that method as part of the public API?

Activity

  1. curran commented on Jul 24, 2021

    @curran
    ContributorAuthor

    I have a feeling Racer might support this.

  2. curran commented on Jul 24, 2021

    @curran
    ContributorAuthor

    I notice that createSubscribeQuery has options.results, described as "Prior query results, if available, such as from server rendering." However it's not clear how to generate these results and what type of objects they are expected to be.

    Should results be an array of Doc instances? If so, how would one go about populating them? Could one call doc.ingestSnapshot for each of those? For that, we'd need an array of Snapshots corresponding to query results. For that, it would indeed be useful to have a utility method on Doc that generates a Snapshot. If we had that, we could iterate over results from a fetched query and serialize that during server rendering.

  3. curran commented on Feb 27, 2022

    @curran
    ContributorAuthor

    I'm still trying to figure out how to do this. The Racer logic does not appear to be directly usable.

    It seems that connection.createSubscribeQuery() from the client side (as seen in Leaderboard) is the most common approach, but has anyone experimented with server rendering query results? Are there any examples out there where the query is executed in the server, then the results are deserialized and instantiated client side?

    I understand that connection.createSubscribeQuery(collection, query [, options [, callback]]) can be invoked where options.results is defined, but how exactly to define it is not clear.

    The documentation states:

    • options.results – Object[]
    • Prior query results, if available, such as from server rendering

    But what kind of Object[] should it be? An array of snapshots? An array of fetched Docs? An array of subscribed Docs?

    I am also unable to find any test code that populates options.results (in test/client/query-subscribe.js).

    Thanks in advance!

  4. ericyhwang commented on Mar 1, 2022

    @ericyhwang
    Contributor

    The source code lists options.results as an array of Doc instances, as obtained from connection.get(collection, id):

    // If present, the callback should have the signature function(error, results, extra)
    // where results is a list of Doc objects.
    Connection.prototype.createSubscribeQuery = function(collection, q, options, callback) {
    return this._createQuery('qs', collection, q, options, callback);
    };

    I'll update the docs to indicate the specific type of options.results!

    To initially populate a Doc on the client based on server-rendered data, you'd use Doc#ingestSnapshot

  5. curran commented on Mar 1, 2022

    @curran
    ContributorAuthor

    Thank you @ericyhwang for investigating!

    To summarize:

    • options.results is expected to be an array of Doc instances, as obtained from connection.get(collection, id).
    • We can invoke doc.ingestSnapshot on each Doc, but we do not need to fetch or subscribe them.
    • The internals of createSubscribeQuery will handle subscribing to changes in those Docs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions