Client GraphQL proposal: Use `TypedDocumentNode`
Created by: umpox
Changes
This proposal brings 3 main changes:
- We generate
TypedDocumentNode
queries and update our GraphQL fetching functions to support this in addition tostring
- We write our queries in
.graphql
files instead of asgql
strings. - We generate co-located
Component.queries.ts
files instead of pushing everything into a largegraphql-operations
file.
Benefits
- We can automatically infer types using
TypedDocumentNode
. For example,requestGraphQL<SomeResult, SomeVariables>(Query)
becomes justrequestGraphQL(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 extractDocumentNode
fromstring
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 ats
/tsx
file. Currently even just saving a file that contains agql
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 theyarn 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.