Skip to content

Client GraphQL proposal: Use `TypedDocumentNode`

Administrator requested to merge tr/use-typed-document-nodes into main

Created by: umpox

Changes

This proposal brings 3 main changes:

  1. We generate TypedDocumentNode queries and update our GraphQL fetching functions to support this in addition to string
  2. We write our queries in .graphql files instead of as gql strings.
  3. We generate co-located Component.queries.ts files instead of pushing everything into a large graphql-operations file.

Benefits

  • We can automatically infer types using TypedDocumentNode. For example, requestGraphQL<SomeResult, SomeVariables>(Query) becomes just requestGraphQL(QueryDocument) after this change. This makes it much easier to correctly type functions and improves code readability.
  • Using TypedDocumentNode results in better compatibility with external GraphQL libraries. For example, we would no longer have to use our util wrappers that extract DocumentNode from string queries.
  • We get a better separation of concerns by using .graphql files. This works well with our CSS modules migration, components can now declare their logic, styles and queries separately. This also means we no longer need to regenerate all GraphQL types whenever you make any change in a ts/tsx file. Currently even just saving a file that contains a gql string results in full type regeneration, which is slow and frustrating. This approach means the types will only be regenerated when .graphql files are modified, which will happen much less often.
  • We can remove the giant graphql-operations file. We should only need this for the (Web|Shared|Browser)GraphQlOperations interface which is used in integration tests. This means it's much easier to understand where types are being shared from. We have quite a few cases in the codebase where types are shared across many unrelated components. Updating one of these queries means having to adjust all of these components, when is likely to be undesirable.

Drawbacks

  • Adding fragments to a query is slightly different. Previously we would inject fragments into the gql string, we no longer need to do that and can just use them as normal in GraphQL. This works great for fragments in the same file, but we have some cases where we import fragments from other files. We don't get Go-To-Definition or autocompletion on those fragments. Any errors are caught at the yarn generate step instead.
  • In some cases, it may be less readable this way. For example, it might be easier to understand a query when viewing a small function that has an inlined gql string.

Questions

Can we use gql strings with TypedDocumentNode? We could, but we'd end up declaring the query twice (once through gql and once through the generated TypedDocumentNode). The unused gql query wouldn't be automatically tree-shaken out of the bundle

How would we migrate? It should be possible to fully migrate quite quickly by writing a codemod. Wouldn't plan to merge this without having a codemod prepared.

Merge request reports

Loading