Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple useFragment uses for same fragment data creates large transport size #344

Closed
maciesielka opened this issue Aug 18, 2024 · 3 comments

Comments

@maciesielka
Copy link

👋🏻 We're working on optimizing our Next.js App Router usage as much as we can and came into some possibly unexpected behavior related to the streaming support offered by this package. If this turns out to be expected behavior, that'd still be useful for us to know as well 🙂

Overview

We rely on useFragment to deliver cache updates for singleton data (not unlike a setup similar to what's described by AllProducts in this documentation) to many different components that are rendered at once. Despite the same fragment, each usage of useFragment seems to contribute linearly to the size of the script tag that manages the ApolloSSRDataTransport in the browser as a part of the SSR streaming process. Since we are subscribing to updates for the same location in the cache, we'd expect some kind of deduplication or normalization to prevent so much redundancy.

Example

You can find a reproducing project forked from this repo here.

In order to visualize the problem, follow these steps:

  1. Run the project with yarn dev

  2. Navigate to the new page that uses just one useFragment call at: http://localhost:5001/cc/use-fragment/1

    1. Inspect the page source / ApolloSSRDataTransport script tag for this page

      A pretty-printed example is shown below:
      <script>
        (window[Symbol.for("ApolloSSRDataTransport")] ??= []).push({
          rehydrate: {
            ":Rkvff7qcq:": {
              data: {
                poll: {
                  __typename: "Poll",
                  id: "1",
                  question: "What's your favorite thing about GraphQL?",
                  totalVotes: 4315,
                  answers: [
                    {
                      __typename: "Answer",
                      id: "1",
                      text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                      votes: 1867,
                      percentage: 43.26767091541136,
                    },
                    {
                      __typename: "Answer",
                      id: "2",
                      text: "I get to spend less time writing documentation and more time actually building features.",
                      votes: 787,
                      percentage: 18.238702201622246,
                    },
                    {
                      __typename: "Answer",
                      id: "3",
                      text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                      votes: 1191,
                      percentage: 27.60139049826188,
                    },
                    {
                      __typename: "Answer",
                      id: "4",
                      text: "It makes me feel like a wizard who can magically summon any data I need!",
                      votes: 470,
                      percentage: 10.89223638470452,
                    },
                  ],
                },
              },
              networkStatus: 7,
            },
            ":R3kvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
          },
          events: [
            {
              type: "data",
              id: "1",
              result: {
                data: {
                  poll: {
                    __typename: "Poll",
                    id: "1",
                    question: "What's your favorite thing about GraphQL?",
                    totalVotes: 4315,
                    answers: [
                      {
                        __typename: "Answer",
                        id: "1",
                        text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                        votes: 1867,
                        percentage: 43.26767091541136,
                      },
                      {
                        __typename: "Answer",
                        id: "2",
                        text: "I get to spend less time writing documentation and more time actually building features.",
                        votes: 787,
                        percentage: 18.238702201622246,
                      },
                      {
                        __typename: "Answer",
                        id: "3",
                        text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                        votes: 1191,
                        percentage: 27.60139049826188,
                      },
                      {
                        __typename: "Answer",
                        id: "4",
                        text: "It makes me feel like a wizard who can magically summon any data I need!",
                        votes: 470,
                        percentage: 10.89223638470452,
                      },
                    ],
                  },
                },
              },
            },
            { type: "complete", id: "1" },
          ],
        });
      </script>
  3. In a new tab, navigate to the new page that uses 24 of the same useFragment call at: http://localhost:5001/cc/use-fragment/24

    1. Inspect the page source / ApolloSSRDataTransport script tag for this page. Compare it to the results in step 2.i and see that it's considerably larger and full of mostly redundant information

      Find a pretty-printed example below that includes 23 more duplicate entries for the same Poll data
      <script>
        (window[Symbol.for("ApolloSSRDataTransport")] ??= []).push({
          rehydrate: {
            ":Rkvff7qcq:": {
              data: {
                poll: {
                  __typename: "Poll",
                  id: "1",
                  question: "What's your favorite thing about GraphQL?",
                  totalVotes: 4315,
                  answers: [
                    {
                      __typename: "Answer",
                      id: "1",
                      text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                      votes: 1867,
                      percentage: 43.26767091541136,
                    },
                    {
                      __typename: "Answer",
                      id: "2",
                      text: "I get to spend less time writing documentation and more time actually building features.",
                      votes: 787,
                      percentage: 18.238702201622246,
                    },
                    {
                      __typename: "Answer",
                      id: "3",
                      text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                      votes: 1191,
                      percentage: 27.60139049826188,
                    },
                    {
                      __typename: "Answer",
                      id: "4",
                      text: "It makes me feel like a wizard who can magically summon any data I need!",
                      votes: 470,
                      percentage: 10.89223638470452,
                    },
                  ],
                },
              },
              networkStatus: 7,
            },
            ":R3kvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R5kvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R7kvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R9kvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":Rbkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":Rdkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":Rfkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":Rhkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":Rjkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":Rlkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":Rnkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":Rpkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":Rrkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":Rtkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":Rvkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R11kvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R13kvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R15kvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R17kvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R19kvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R1bkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R1dkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R1fkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
            ":R1hkvff7qcq:": {
              data: {
                __typename: "Poll",
                id: "1",
                question: "What's your favorite thing about GraphQL?",
                totalVotes: 4315,
                answers: [
                  {
                    __typename: "Answer",
                    id: "1",
                    text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                    votes: 1867,
                    percentage: 43.26767091541136,
                  },
                  {
                    __typename: "Answer",
                    id: "2",
                    text: "I get to spend less time writing documentation and more time actually building features.",
                    votes: 787,
                    percentage: 18.238702201622246,
                  },
                  {
                    __typename: "Answer",
                    id: "3",
                    text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                    votes: 1191,
                    percentage: 27.60139049826188,
                  },
                  {
                    __typename: "Answer",
                    id: "4",
                    text: "It makes me feel like a wizard who can magically summon any data I need!",
                    votes: 470,
                    percentage: 10.89223638470452,
                  },
                ],
              },
              complete: true,
              missing: undefined,
            },
          },
          events: [
            {
              type: "data",
              id: "1",
              result: {
                data: {
                  poll: {
                    __typename: "Poll",
                    id: "1",
                    question: "What's your favorite thing about GraphQL?",
                    totalVotes: 4315,
                    answers: [
                      {
                        __typename: "Answer",
                        id: "1",
                        text: "I love how it gives me an excuse to use the word “schema” in casual conversation.",
                        votes: 1867,
                        percentage: 43.26767091541136,
                      },
                      {
                        __typename: "Answer",
                        id: "2",
                        text: "I get to spend less time writing documentation and more time actually building features.",
                        votes: 787,
                        percentage: 18.238702201622246,
                      },
                      {
                        __typename: "Answer",
                        id: "3",
                        text: "It's like a buffet where I can pick and choose exactly what data I want, without any unwanted side dishes.",
                        votes: 1191,
                        percentage: 27.60139049826188,
                      },
                      {
                        __typename: "Answer",
                        id: "4",
                        text: "It makes me feel like a wizard who can magically summon any data I need!",
                        votes: 470,
                        percentage: 10.89223638470452,
                      },
                    ],
                  },
                },
              },
            },
            { type: "complete", id: "1" },
          ],
        });
      </script>
  4. Feel free to continue testing with as many fragments as you'd like to see how it affects the transport. The number of rendered items is configurable in the URL:

    /cc/use-fragment/[num-items]
    
@phryneas
Copy link
Member

phryneas commented Aug 19, 2024

I fear there's no real way around that :(

Let me try to explain:

What you see here is not us transporting cache data - it's something different: we transport a snapshot of your hook, to prevent React rehydration errors.

The problem here is twofold:

  • hooks that render on the server don't immediately render in the browser, they can wait (for a very long time) for a hydration boundary to finish
  • Apollo Client is a normalized cache, so responses to other queries or mutations can influence the cache value of a different hook

So there is a possible scenario where your useFragment renders on the server (so the HTML is already generated and flushed to the browser), but doesn't get rehydrated and added to your visible Browser DOM because of something else suspending in the same tree for a long amount of time.
Meanwhile, in the browser a cache update happens that would result in a different result to that useFragment call.
Once your suspended tree finally finishes on the server, the HTML is added to the visible DOM and React re-runs the component to see if it would actually render the same.
You get a hydration mismatch error. And while usually, a hydration mismatch is something React can recover from by throwing away all work from the server and restarting everything on the client, I've seen cases where it completely crashed the page. Also, depending on your architecture, this can be a lot of work.

The whole thing looks like this (taken from my RFC).

sequenceDiagram
  participant GQL as Graphql Server

  box gray Server
  participant SSRCache as SSR Cache
  participant SSRA as SSR Component A
  end
  participant Stream

  box gray Browser
  participant BCache as Browser Cache
  participant BA as Browser Component A
  end

  participant Data as External Data Source

  SSRA ->> SSRA: render
  activate SSRA
  SSRA -) SSRCache: query
  activate SSRCache
  Note over SSRA: render started network request, suspend
  SSRCache -) GQL: query A
  GQL -) SSRCache: query A result
  SSRCache -) SSRA: query A result
  SSRCache -) Stream: serialized query A result
  deactivate SSRCache
  Stream -) BCache: add query A result to cache
  SSRA ->> SSRA: render
  Data -) BCache: cache update
  SSRA ->> SSRA: other children of the suspense boundary still need more time
  Note over SSRA: render successful, suspense finished
  SSRA -) Stream: transport
  deactivate SSRA
  Stream -) BA: restore DOM
  BA ->> BA: rehydration render
  Note over BA: ⚠️ rehydration mismatch, data changed in the meantime

Loading

So, to prevent these hydration errors, we essentially snapshot the value a hook had at the time it rendered first on the server, transport that over, render it once with that value, and if it differs from the actual cache contents, we immediately rerender with the current cache contents.

All to prevent that hydration mismatch 🤦

Now, the thing is: each of those is a snapshot of that individual hook, at that individual point in time. All of these are not the same object, and they could have slight variances.
So deduplicating them is hard, and it adds a lot of bundle size that in most use cases is a lot more than the data you actually save.
So we don't.

That said, we do have escape hatches you could use to try and add your own deduplication logic (and if you come up with something good, please share it!):

buildManualDataTransport accepts an optional stringifyForStream and reviveFromStream callback option, and you could use that to create a modifed version of ApolloNextAppProvider.
Here's the "normal" implementation without those options:

export const ApolloNextAppProvider = /*#__PURE__*/ WrapApolloProvider(
buildManualDataTransport({
useInsertHtml() {
const insertHtml = useContext(ServerInsertedHTMLContext);
if (!insertHtml) {
if (process.env.REACT_ENV === "browser") {
//Allow using the browser build of ApolloNextAppProvider outside of Next.js, e.g. for tests.
return () => {};
}
throw new Error(
"The SSR build of ApolloNextAppProvider cannot be used outside of the Next App Router!\n" +
'If you encounter this in a test, make sure that your tests are using the browser build by adding the "browser" import condition to your test setup.'
);
}
return insertHtml;
},
})
);
ApolloNextAppProvider.info = bundle;

@maciesielka
Copy link
Author

@phryneas thanks for the quick and super-detailed response! This helps our understanding of this particular problem and the streaming functionality 10x.

I'll close this since there's no action item here.

Copy link
Contributor

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants