Skip to content

Conversation

@janettec
Copy link

@janettec janettec commented Sep 12, 2025

Why these changes?

Fragments are not for reuse.

The current language in section 2.8 on Fragments, namely the sentence...

Fragments allow for the reuse of common repeated selections of fields, reducing duplicated text in the document.

...encourages using fragments to deduplicate common selections, even if those selections represent independent data needs.

For example, let's consider these two functions

// This function formats a post for display in a feed
func formatPostForFeed(post: PostDisplayFragment) -> String {
 let authorName = post.author.name
 let contentText = post.content.text

 return "\(authorName) posted: \(contentText)"
}

// This function formats a post for notification purposes
func formatPostForNotification(post: PostDisplayFragment) -> String {
 let authorName = post.author.name
 let contentText = post.content.text

 return "New post from \(authorName): \(contentText)"
}

Given these two functions currently both use authorName and contentText, the current language in the spec encourages one to write a fragment

fragment PostDisplayFragment on Post {
 author
 content
}

If formatPostForFeed now needs timestamp, we will add naturally add timestamp to PostDisplayFragment

// This function formats a post for display in a feed
func formatPostForFeed(post: PostDisplayFragment) -> String {
 let authorName = post.author.name
 let contentText = post.content.text
 let timestamp = post.createdAt.formatted // Added

 return "\(authorName) posted: \(contentText)\nPosted \(timestamp)"
}
fragment PostDisplayFragment on Post {
 author
 content
 timestamp # Added
}

If we have the following queries

query NotificationQuery {
 ...PostDisplayFragment # Over-fetching timestamp
}

query FeedQuery {
 ...PostDisplayFragment
}

notice how NotificationQuery is now over-fetching timestamp!

The key observation is that formatPostForFeed and formatPostForNotification are two independent functions, so by having them both rely on a single fragment to express their data needs, we are creating a dependency where one should not exist (because that dependency does not exist in the product logic itself).

What are the proposed changes?

Updated:

  1. The description for why one might use fragments
  2. The first GraphQL example in section 2.8

The goal is to emphasize that fragments support evolving data needs (as opposed to recommending people identify common selections that are currently in an executable document).

Open to any and all feedback on the motivation for the change and how it's communicated via changes in the spec language!

@netlify
Copy link

netlify bot commented Sep 12, 2025

Deploy Preview for graphql-spec-draft ready!

Name Link
🔨 Latest commit df32811
🔍 Latest deploy log https://app.netlify.com/projects/graphql-spec-draft/deploys/68e935b26f2fc70008bffb5d
😎 Deploy Preview https://deploy-preview-1193--graphql-spec-draft.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@janettec janettec changed the title Update description of Fragments to emphasize composability Update description of Fragments to emphasize evolving data needs Sep 12, 2025
@benjie
Copy link
Member

benjie commented Sep 12, 2025

Definitely agree on the motivation for this change; thanks for the submission Janette!

@andimarek
Copy link
Contributor

I think that is is great change overall. The challenge is a bit to make it understandable in the context of the spec.

Using fragments to declare data needs (like in relay) always requires something on top of the spec to make it work. So we would have to make this clear somehow.

Copy link
Contributor

@martinbonnin martinbonnin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple comments but otherwise very supportive of updating that language!

Copy link
Member

@benjie benjie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling the logic friendProfile and the fragment friendProfile is confusing. Can we differentiate the logic - e.g. just call it "profile rendering logic" (prose) rather than using code? (Not sure if this is the best fix.)

duplicated text in the document. Inline Fragments can be used directly within a
selection to condition upon a type condition when querying against an interface
or union.
Fragments allow for the definition of modular selection sets that make it easier
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to flush out what modular means. Matt + Pascal's suggestion: single purpose.

Comment on lines 590 to 591
Fragments allow for the definition of modular selection sets that make it easier
to add and remove selections as needed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe something along the lines of (written whilst on Zoom, not final wording!):

Fragments allow client components and logic to describe their specific
data requirements locally. Fragments can then be composed together to
form a GraphQL operation to issue to the server.

@janettec
Copy link
Author

Just updated based off some of the feedback from the working group meeting!

  • Removed the word modular and opted for something more prescriptive based on people's suggestions ("should declare its data needs in a dedicated fragment"). Let me know if "should" is too strong here (I think it makes sense based off this guidance, but open to discussion!)
  • Instead of referencing a function friendProfile, use prose as suggested by @benjie

@martinbonnin
Copy link
Contributor

The video is just out. Can we merge this and iterate on the wording if needed. I'd love the message to be consistent.

Copy link
Member

@michaelstaib michaelstaib left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good!

Copy link
Member

@benjie benjie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how Lee feels about using _ in fragment names, but I'd be tempted to adopt Relay naming conventions here and be super explicit.

Perhaps we could lay out the entire scenario showing multi-level composition?

Example

Each data-consuming component (function, class, UI element, and so on) of a client application should declare its data needs in a dedicated fragment. These fragments may then be composed, following the usage of the components themselves, to form a GraphQL operation to issue to the server.

Consider a social media app. The userCard(user, layout) function renders a tiny details card about a user for inclusion in other components. For this, it requires certain information about the user which we can describe with a fragment dedicated to this purpose:

fragment userCard_user on User {
  id
  name
  profilePic(size: 50)
}

When rendering a user's profile with the userProfile(user) function, the userCard can be used to display each of the user's friends and mutual friends. The userProfile() function does not need to know about the specific requirements of the userCard() function since it can simply compose it's dedicated fragment in the relevant places:

fragment userProfile_user on User {
  id
  name
  profilePic(size: 250)
  biography
  friends(first: 10) {
    ...userCard_user
  }
  mutualFriends(first: 10) {
    ...userCard_user
  }
}

This fragment can be used whenever a user profile is displayed, for example when hovering over a user, or on their dedicated user profile page (which may also need to compose fragments for additional concerns):

query userProfilePage($id: Int!) {
  user(id: $id) {
    ...userProfile_user
  }
  ...sideBar_query
  ...titleBar_query
}

Comment on lines +590 to +592
Each client component should declare its data needs in a dedicated fragment.
These fragments may then be composed in the same fashion as the components
themselves to form a GraphQL operation to issue to the server.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm concerned that "component" here will be read too specifically (e.g. to mean a React component) rather than broadly (e.g. a "component" of client logic such as a function, class, or other...). Perhaps something along the lines of:

Suggested change
Each client component should declare its data needs in a dedicated fragment.
These fragments may then be composed in the same fashion as the components
themselves to form a GraphQL operation to issue to the server.
Each data-consuming component (function, class, UI element, and so on) of
a client application should declare its data needs in a dedicated fragment.
These fragments may then be composed, following the usage of the components
themselves, to form a GraphQL operation to issue to the server.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth noting here that this places a should on the client not the server.

@Tobbe
Copy link

Tobbe commented Nov 6, 2025

Each data-consuming component (function, class, UI element, and so on) ...

I like this! The spec should be as framework and implementation agnostic as possible

Perhaps we could lay out the entire scenario showing multi-level composition?

Yes! This is great. I'm hearing from our users (RedwoodJS/CedarJS) that fragments are seen as a very advanced concept. A full example like this really helps.
Maybe the text could be even clearer with the fact that it's entirely natural for a component having to include both the "code definition" (i.e. function signature) and the "data definition" (i.e. fragment) of any children it wants to render.

(And when this change lands, I'll definitely have to update the Cedar docs on fragments)

@leebyron
Copy link
Collaborator

leebyron commented Nov 6, 2025

I don't know how Lee feels about using _ in fragment names,

Would like to keep examples camel case in the spec

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

Successfully merging this pull request may close these issues.

8 participants