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

GraphQL Code Generator v5 Roadmap #8296

Open
17 of 79 tasks
theguild-bot opened this issue Aug 29, 2022 · 61 comments
Open
17 of 79 tasks

GraphQL Code Generator v5 Roadmap #8296

theguild-bot opened this issue Aug 29, 2022 · 61 comments
Assignees
Labels
core Related to codegen core/cli

Comments

@theguild-bot
Copy link
Collaborator

theguild-bot commented Aug 29, 2022

This page is synced automatically from The Guild's Notion
Notion page URL: https://www.notion.so/GraphQL-Code-Generator-v4-Roadmap-91923bfb2dee48eaa0d6a77666429968

At The Guild, we’ve decided to work as much as possible in public; that’s why we are opening the roadmaps for all of our projects.

The goals for this are:

  1. So you will know what we are working on, what we see as a higher priority, and know what to expect from our projects in the future
  2. So you can share your opinions and thoughts about what we do and influence our decisions
  3. So you can join us and contribute to our efforts!

Before laying down the roadmap of GraphQL Code Generator v3, we would like to thank all of you for being so many who use codegen daily and for contributing to making it such a complete project! 🚀

While some people judge that GraphQL is difficult, GraphQL Code Generator v3 aims to change that perspective by providing a unified configuration along with a smaller and simpler generated code.

By providing a unified package and configuration for all client-side use cases, all existing and future plugin alternatives will be moved to community repos.

Let’s now cover these changes in detail.

A unified configuration and package for all GraphQL clients

Most of the existing client-side plugins (typescript-react-apollo, typescript-react-query, etc) rely on the generation of hooks or SDKs that wrap the underlying GraphQL Client in a type-safe way.

However, the generation of hooks or SDK code brings many downsides:

  • an unnecessary increase of the final bundle size
  • misalignment between the generated hooks signature and the underlying GraphQL Client
  • inconsistencies of configuration options and preset compatibility across packages (ex: near-operation-file compatibility)

To make GraphQL code generation great and simple, the v3 version will introduce two major changes:

  • a new unique preset for all GraphQL clients, which include better developer experience, smaller bundle size, stronger typings, and easier-to-follow best practices
  • a TypeScript-first configuration file that will allow configuration autocompletion

Here is how you can already configure codegen for all GraphQL Clients:

import { CodegenConfig } from '@graphql-codegen/cli'

const config: CodegenConfig = {
  schema: 'http://localhost:4000/graphql',
  documents: ['src/**/*.tsx'],
  generates: {
    './src/gql/': {
      preset: 'client',
      plugins: []
    }
  }
}

export default config

The client preset comes with a simple opinionated configuration and a lightweight types-only generation.

To try the new client preset, please install the following dependencies:

yarn add graphql
yarn add -D typescript
yarn add -D @graphql-codegen/cli
yarn add -D @graphql-codegen/client-preset

First, start GraphQL Code Generator in watch mode:

yarn graphql-codegen --watch

Using GraphQL Code Generator will type your GraphQL Query and Mutations as you write them ⚡️

Now, each query or mutation written with the generated graphql() function will be automatically typed!

For example, with Apollo Client (React):

import React from 'react';
import { useQuery } from '@apollo/client';
import { graphql } from './gql/gql';

import Film from './Film';

// here, `allFilmsWithVariablesQueryDocument` is fully typed!
const allFilmsWithVariablesQueryDocument = graphql(/* GraphQL */ `
  query allFilmsWithVariablesQuery($first: Int!) {
    allFilms(first: $first) {
      edges {
        node {
          ...FilmItem
        }
      }
    }
  }
`);

function App() {
	// Most GraphQL Clients know how to deal with typed GraphQL documents,
	//   providing typed data and typed variables
  const { data } = useQuery(allFilmsWithVariablesQueryDocument, { variables: { first: 10 } });
  return (
    <div className="App">
      {data && <ul>{data.allFilms?.edges?.map((e, i) => e?.node && <Film film={e?.node} key={`film-${i}`} />)}</ul>}
    </div>
  );
}

export default App;

Thanks to work made to integrate TypeDocumentNode (the underlying plugin used by preset: client) with most of the popular GraphQL clients, you no longer need hooks or SDK, simple GraphQL documents works!

We believe that the preset: client approach is the way to get the best of TypeScript and GraphQL by:

  • reducing the size of the generated bundle
  • only the graphql() function needs to be imported (no type, hooks, document imports)
  • removing layers between your application and your chosen GraphQL Client
  • providing stronger typings that will stay aligned with your chosen GraphQL Client
  • offering you the best component isolation design by leveraging Fragment Masking

Finally, this new preset: client has been properly tested on all popular GraphQL clients across most frameworks:

  • React
    • @apollo/client (since 3.2.0, not when using React Components (<Query>))
    • @urql/core (since 1.15.0)
    • @urql/preact (since 1.4.0)
    • urql (since 1.11.0)
    • graphql-request (since 5.0.0)
    • react-query (with graphql-request@5.0.0)
    • swr (with graphql-request@5.0.0)
    • @urql/exchange-graphcache (since 3.1.11)
  • Svelte
    • @urql/svelte (since 1.1.3)
  • Vue
    • @vue/apollo-composable (since 4.0.0-alpha.13)
    • villus (since 1.0.0-beta.8)
    • @urql/vue (since 1.11.0)
  • Others
    • graphql-js (since 15.2.0)
    • graphql-request (since 5.0.0)

You will find demos and code examples for each of them in the examples/front-end/ folder of the codegen repository.

You will also find a complete guide for React and Vue in codegen documentation.

We aim for GraphQL Code Generator 3.0’s client preset to become the official way to generate GraphQL Types for front-end use cases, replacing all existing hook and SDK-based plugins.

For this reason, we encourage you to already give a try at the codegen v3 client preset (@graphql-codegen/client-presec) and provide feedback on this issue.

The v3 stable release will be shipped once sufficient feedback is posted.

Finally, while the GraphQL Code Generator 3.0 milestone aims to provide a unified front-end experience through the preset: client, the 3.x versions aim to fully rewrite the core packages of codegen.

Some core parts of codegen are more than 6 years old and need to be rewritten (optimized, simplified, and more).

We plan to incorporate the pending issues related to the core packages in this gradual 3.x milestones.

Introduction of the “community plugins”

Historically, all plugins were pushed to the https://github.com/dotansimha/graphql-code-generator repository, making it hard for us to review all contributions in a reasonable timeframe and to enforce consistency across all the options introduced in the different packages.

We believe that the best way to keep codegen extensible and improve the contribution experience at scale is to introduce the concept of community plugins.

A community plugin offers a feature-set that diverges from the preset: client or a plugin created by the community.

Soon, all the existing plugins part of the list below and all the future plugins created by the community will live in their dedicated repository:

  • @graphql-codegen/typescript-react-apollo
  • @graphql-codegen/typescript-graphql-request
  • @graphql-codegen/typescript-apollo-angular
  • @graphql-codegen/typescript-apollo-client-helpers
  • @graphql-codegen/typescript-react-query
  • @graphql-codegen/typescript-urql
  • @graphql-codegen/named-operations-object
  • @graphql-codegen/urql-introspection
  • @graphql-codegen/flow-resolvers
  • @graphql-codegen/typescript-vue-apollo
  • @graphql-codegen/typescript-rtk-query
  • @graphql-codegen/flow-operations
  • @graphql-codegen/typescript-msw
  • @graphql-codegen/typescript-mongodb
  • @graphql-codegen/typescript-type-graphql
  • @graphql-codegen/jsdoc
  • @graphql-codegen/typescript-vue-urql
  • @graphql-codegen/kotlin
  • @graphql-codegen/typescript-vue-apollo-smart-ops
  • @graphql-codegen/java
  • @graphql-codegen/c-sharp-operations
  • @graphql-codegen/hasura-allow-list
  • @graphql-codegen/typescript-stencil-apollo
  • @graphql-codegen/relay-operation-optimizer
  • @graphql-codegen/typescript-oclif
  • @graphql-codegen/java-resolvers
  • @graphql-codegen/java-apollo-android

All the above plugins will be eligible for repository ownership transfer based on relevant past contributions.

Of course, such a change will come with help from our side:

  • We will create a new “Create a plugin” guide that will provide complete information and guidelines (ex: publishing, codegen APIs, adding your plugin to the codegen hub)
  • Since each community plugin will live in its own repository, we will provide a proper Github repository template with building and publishing CI tools configured.

What about server-side plugins?

The 3.x milestones include some work on server-side plugins such as typescript-resolvers (ex: improving Federation support).


Milestones

Below are the details of the aforementioned plans for the 3.0 and 3.x milestones.

3.0

3.x

preset: client improvements

Future of codegen CLI

Back-end code generation issues

We will go over the following typescript-resolvers and graphql-modules pending plugins issues:

@charlypoly charlypoly pinned this issue Aug 29, 2022
@charlypoly charlypoly self-assigned this Aug 29, 2022
@huv1k
Copy link

huv1k commented Aug 30, 2022

Will there be support for module augmentation still? 🤔 I really enjoy this feature, but there are some shortcomings like some frameworks don't provide for example useFragment etc.

@charlypoly
Copy link
Contributor

Will there be support for module augmentation still? 🤔 I really enjoy this feature, but there are some shortcomings like some frameworks don't provide, for example, useFragment etc.

Hi @huv1k!
We are planning to remove the support for module augmentation since it is not working without the associated babel plugin properly set up.
Since not all front-end setups can provide custom babel configuration, we were planning to remove the augmentedModuleName options and also to simplify the installation flow.

However, this being an RFC, we will take your feedback into account! 👀

@franky47
Copy link

franky47 commented Aug 31, 2022

Based on your code example, does that mean that the preferred way to consume GraphQL operations is co-location within TS/JS files?

I just migrated a large codebase from Apollo CLI to graphql-codegen v2 and refactored it to move all GraphQL operation definitions to .graphql files (importing only typed documents to pass to Apollo Client), I wouldn't want to have to undo that all over again..

@charlypoly
Copy link
Contributor

Based on your code example, does that mean that the preferred way to consume GraphQL operations is co-location within TS/JS files?

I just migrated a large codebase from Apollo CLI to graphql-codegen v2 and refactored it to move all GraphQL operation definitions to .graphql files (importing only typed documents to pass to Apollo Client), I wouldn't want to have to undo that all over again..

Hi @franky47,

We are exploring different migration path options; providing a codemod could be one; however, we have to look at the different setups to migrate from.
What plugins are you currently using?

@franky47
Copy link

Hi @charlypoly, here's my codegen.yml:

overwrite: true
schema: "../backend/schema.graphql"
documents: "src/**/*.graphql"
config: # The following configuration will adjust output to the defaults of Apollo-Codegen, and should be compatible with most use-cases.
  preResolveTypes: true # Simplifies the generated types
  namingConvention: keep # Keeps naming as-is
  avoidOptionals: # Avoids optionals on the level of the field
    field: true
  nonOptionalTypename: true # Forces `__typename` on all selection sets
  skipTypeNameForRoot: true # Don't generate __typename for root types
generates:
  src/modules/graphql.types.ts:
    plugins:
      - typescript
      - typescript-operations
      - typed-document-node
    hooks:
      afterOneFileWrite:
        - prettier --write

I have GraphQL code into .graphql files, which are parsed by the generator to give me the full schema types (I use them to type props in a React/Next.js app), and typed schemas to pass to Apollo Client, which provides type inference (variables & output), so that TypeScript has my back when matching the data & view layers.

I migrated from a setup where the Apollo CLI generated the TS types from gql tags co-located with their components in .ts(x) files, hence my remark that having to go back would be quite annoying.

I really like the typed document plugin, it removed the need to explicitly pass generic arguments to useQuery and useMutation, so most of my query/mutation hooks are now one-liners. The only thing that required a bit of refactoring to use those was that their naming convention does not seem to be configurable, so I had to rename all FOO_{QUERY|MUTATION} to FooDocument, not a big deal but the name can be confusing sometimes (especially when dealing with domain objects also named "Document").

Hope this helps you see a bit better about my particular use-case.

@charlypoly
Copy link
Contributor

@franky47, thank you for sharing it!

We are also exploring options to still support .graphql files, we will keep you updated here.

@nandita1

This comment was marked as resolved.

@productdevbook

This comment was marked as off-topic.

@ilijaNL
Copy link

ilijaNL commented Sep 9, 2022

If it is going full TypeDocumentNode way (which I like), is it not better to go with a builder pattern approach. The builder can be full type safe and be generated from the introspection query. Additionally you need to generate the builder only initially and on schema change and not when adding new documents. Some open source projects which apply this principle:

In my opinion this provides best of the worlds. Small bundle size, no watchers necessary on frontend and much faster dev cycle.
Additionally the builder can be scoped per context (think about hasura roles or public/private introspection results)

@hrougier
Copy link

hrougier commented Sep 14, 2022

Will there be support for module augmentation still? 🤔 I really enjoy this feature, but there are some shortcomings like some frameworks don't provide, for example, useFragment etc.

Hi @huv1k! We are planning to remove the support for module augmentation since it is not working without the associated babel plugin properly set up. Since not all front-end setups can provide custom babel configuration, we were planning to remove the augmentedModuleName options and also to simplify the installation flow.

However, this being an RFC, we will take your feedback into account! 👀

Augmented module is a nice feature for people who don't like having their own source code polluted by/relying on generated code, why not keeping it for those willing to make advanced configuration? (babel plugin is just a one line configuration).

Inspired by what graphql-let does, I personally came up with some kind of hack that generates everything to a fake node_modules/@types of a monorepo:

schema: path/to/schema.json
documents:
  - src/**/*.ts
  - src/**/*.tsx
generates:
  # app operations are generated inside a fake @types module
  ../../node_modules/@types/myProject__graphql-client:
    preset: gql-tag-operations-preset
    presetConfig:
      augmentedModuleName: '@myProject/graphql-client'
      fragmentMasking:
        augmentedModuleName: '@myProject/graphql-client'
hooks:
  # here is the ugliest part of the "hack": generating a package.json
  afterAllFileWrite:
    - "printf '{ \"name\": \"@types/myProject__graphql-client\", \"types\": \"gql.d.ts\" }' > '../../node_modules/@types/myProject__graphql-client/package.json'"

This allows for everything within an app to be transparently imported from a @myProject/graphql-client (a preconfigured apollo-client module in the monorepo) without ever seeing/dealing with any ugly generated code 😅

Big advantage: I can remove codegen at any time without breaking the code, only losing types!

import { gql, useQuery } from '@myProject/graphql-client'

const MyQuery = gql(`
  query MyQuery {
    ...
  }
`)

const MyComponent = () => {
  const { loading, data, error } = useQuery(MyQuery)

  return <>...</>
}

It would be nice to keep this ability to hide the generated code somewhere.

@grischaerbe

This comment was marked as resolved.

renovate bot added a commit to apollographql/apollo-server that referenced this issue Sep 28, 2022
…on-4) (#6956)

[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@graphql-codegen/cli](https://togithub.com/dotansimha/graphql-code-generator)
| [`2.12.2` ->
`2.13.0`](https://renovatebot.com/diffs/npm/@graphql-codegen%2fcli/2.12.2/2.13.0)
|
[![age](https://badges.renovateapi.com/packages/npm/@graphql-codegen%2fcli/2.13.0/age-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://badges.renovateapi.com/packages/npm/@graphql-codegen%2fcli/2.13.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://badges.renovateapi.com/packages/npm/@graphql-codegen%2fcli/2.13.0/compatibility-slim/2.12.2)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://badges.renovateapi.com/packages/npm/@graphql-codegen%2fcli/2.13.0/confidence-slim/2.12.2)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>dotansimha/graphql-code-generator</summary>

###
[`v2.13.0`](https://togithub.com/dotansimha/graphql-code-generator/blob/HEAD/packages/graphql-codegen-cli/CHANGELOG.md#&#8203;2130)

[Compare
Source](https://togithub.com/dotansimha/graphql-code-generator/compare/8a4ef646f67e4b59ba7ebee2be0b83348e15575f...58c02b7bef0b94403deb8cd810175f4e7fc6abe8)

##### Minor Changes

-
[#&#8203;8302](https://togithub.com/dotansimha/graphql-code-generator/pull/8302)
[`876844e76`](https://togithub.com/dotansimha/graphql-code-generator/commit/876844e7644a917172f09b3c4eb54a2f4c90e4c6)
Thanks [@&#8203;charlypoly](https://togithub.com/charlypoly)! -
**`@graphql-codegen/gql-tag-operations` and
`@graphql-codegen/gql-tag-operations-preset`**

    Introduce a `gqlTagName` configuration option

    ***

    **`@graphql-codegen/client-preset`**

New preset for GraphQL Code Generator v3, more information on the RFC:
[dotansimha/graphql-code-generator#8296

    ***

    **`@graphql-codegen/cli`**

Update init wizard with 3.0 recommendations (`codegen.ts`, `client`
preset)

##### Patch Changes

-
[#&#8203;8302](https://togithub.com/dotansimha/graphql-code-generator/pull/8302)
[`876844e76`](https://togithub.com/dotansimha/graphql-code-generator/commit/876844e7644a917172f09b3c4eb54a2f4c90e4c6)
Thanks [@&#8203;charlypoly](https://togithub.com/charlypoly)! -
dependencies updates:
- Updated dependency [`@graphql-codegen/plugin-helpers@^2.6.2`
↗︎](https://www.npmjs.com/package/@&#8203;graphql-codegen/plugin-helpers/v/2.6.2)
(from `^2.7.1`, in `dependencies`)
- Updated dependency [`@whatwg-node/fetch@^0.3.0`
↗︎](https://www.npmjs.com/package/@&#8203;whatwg-node/fetch/v/0.3.0)
(from `^0.4.0`, in `dependencies`)
- Updated dependency [`cosmiconfig-typescript-loader@4.0.0`
↗︎](https://www.npmjs.com/package/cosmiconfig-typescript-loader/v/4.0.0)
(from `^4.0.0`, in `dependencies`)
- Added dependency [`@babel/generator@^7.18.13`
↗︎](https://www.npmjs.com/package/@&#8203;babel/generator/v/7.18.13) (to
`dependencies`)
- Added dependency [`@babel/template@^7.18.10`
↗︎](https://www.npmjs.com/package/@&#8203;babel/template/v/7.18.10) (to
`dependencies`)
- Added dependency [`@babel/types@^7.18.13`
↗︎](https://www.npmjs.com/package/@&#8203;babel/types/v/7.18.13) (to
`dependencies`)
- Added dependency
[`@graphql-codegen/client-preset@1.0.1-alpha-20220823170145-c93d8aee3`
↗︎](https://www.npmjs.com/package/@&#8203;graphql-codegen/client-preset/v/1.0.1)
(to `dependencies`)
- Updated dependencies
\[[`876844e76`](https://togithub.com/dotansimha/graphql-code-generator/commit/876844e7644a917172f09b3c4eb54a2f4c90e4c6)]:
-
[@&#8203;graphql-codegen/client-preset](https://togithub.com/graphql-codegen/client-preset)[@&#8203;1](https://togithub.com/1).0.1

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click
this checkbox.

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://app.renovatebot.com/dashboard#github/apollographql/apollo-server).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzMi4yMDYuMCIsInVwZGF0ZWRJblZlciI6IjMyLjIwNi4wIn0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@charlypoly

This comment was marked as resolved.

@deathemperor

This comment was marked as resolved.

@sonatard

This comment was marked as resolved.

@dotansimha
Copy link
Owner

Hi What is the difference between preset: client and preset: gql-tag-operations-preset ?

the-guild.dev/blog/unleash-the-power-of-fragments-with-graphql-codegen the-guild.dev/graphql/codegen/plugins/presets/gql-tag-operations-preset

Hi @sonatard,
The client preset is a wrapper on top of gql-tag-operations-preset. It's going to deprecate gql-tag-operations-preset soon, and introduce better integration with GraphQL clients.

@Faithfinder

This comment was marked as resolved.

@charlypoly

This comment was marked as resolved.

@Faithfinder

This comment was marked as resolved.

@joelmukuthu

This comment was marked as resolved.

@n1ru4l
Copy link
Collaborator

n1ru4l commented Nov 21, 2022

Hello team, great work, love it! Question:

Create a TypedDocumentNode string alternative (TypedString) that does not require GraphQL AST on the Client (should be easily configurable within the preset)

Does this mean that it would be a goal to output the original GraphQL string instead of a document when generating things?

If so, that would be wonderful. (Is it currently possible but just not part of the client preset yet? Or just not possible at all right now?)

We've had issues in the past because of the GraphQL AST parser slowing down our websites, so we've had to pass on using GraphQL code generator for the time being. However, if we could get all the automatically-typed goodness, but without graphql-tag / GraphQL AST parsing at runtime, that would be great. (For context, we're using Remix, which uses ESBuild, so we can't use any of the listed preprocessing tricks either)

Or maybe I'm missing something and this is all possible already? Forgive me if that's true.

Thanks!

@frehner exactly, basically we can bake in the type into anything.
Here is a quick example.

import {DocumentNode} from "graphql"

type WithSignature<TResult, TVariables> = {["    __baked_in_types"]?: (v: TVariables) => TResult }

type ThingWithBakedInType<T, TResult = Record<string, unknown>, TVariables = Record<string, never>> = T & WithSignature<TResult, TVariables>

type TypedString<TResult, TVariables> = ThingWithBakedInType<string, TResult, TVariables>

declare function fetch<TResult, TVariables>(foo: ThingWithBakedInType<unknown, TResult, TVariables>): TResult


declare let foo: TypedString<{a: 1}, {b: 2}>
declare let foo2: ThingWithBakedInType<DocumentNode, {c: 3}>

fetch(foo).a

fetch(foo2).c

https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbwCIQMYFcQFMB2MByEAJlgL5wBmUEIcARAOZQCGYAFgI4A2dAULzACeYLHADqwGGwDKwBjmYx0ULAB4AKgCUsAZ3RcYAGjjqAasyjBmAIy66AfHAC8iANp04nuAH1v15gDWWETewDjeQiI6dAC6APwAXHAAFABuSWYWVra6AJTOjlq6+vCk-JGi6mxhDBJSAEKBwQCSOOrCaurGRXoGznDaqNBEqjowljgMxug4ATgQAO449t3mljZ2Ov2Dw6PjNcY4WKlYUPaOLupwAGTikjJyCkoqGtq9RiZr2Zv25R0mHSI0n2k1exQMqyyGwc-SqNTqbEaQSIrXaIj2EymJjeJUh6xyOl+vBIqC4FlEFBmqBgwAgOEoWBgqDYYPeeO+DmSFAgEAy1UmCKRLTaHVUMzmixw3RxEM+UIJ9lyGRlMH4xKwpPJcDs8G5vIBIiBIIYqgQzCSAEZSMYENYkgAmUi-ElklTaxmUHn2vnw+5ClEi9EoDDYPCEEg21BJADMTv4FEZzK5PNyADpmPHE2xkxB7WnULwgA


Links

@aaronadamsCA
Copy link

With fragmentMasking: false, I thought we were supposed to be using the generated fragment types; but it seems these are in graphql.ts and not re-exported from index.ts. Is this just an oversight, or is there some other way we should be getting back our fragment types? (Obviously we can deep import, but I am assuming index.ts is supposed to be our interface to the generated code.)

I also hope .graphql file support is still being considered; the const someName = graphql(/* GraphQL */`query SomeOtherName { ... }`) pattern is a real eyebrow-raiser that we're frankly not interested in adopting. We would rather keep our GraphQL in GraphQL files and avoid this confusing syntax if possible.

@jstejada
Copy link

jstejada commented Nov 23, 2022

thanks for building this! i'm glad i can use some of the same patterns available in relay with graphql-codegen now

@charlypoly do you have any thoughts on supporting generating multiple files vs single gql.ts/graphql.ts files that contains the runtime nodes for all document definitions?

in a project with a large amount of definitions i would like to be able to not load all of the runtime document nodes upfront unless they're actually being used, and let code-splitting and the bundler just include the ones that are needed.

I noticed that the implementation of the generated graphql function relies on having the documents map to be able to return the corresponding runtime node for a document, but maybe this could work similarly to the relay compiler where the graphql call gets transpiled into an import/require call that imports the corresponding generated file for that document, which would contain the appropriate document node?

alternatively, is there a recommended way to customize the output of the client-preset, maybe to do a custom implementation of this sort of capability?

@charlypoly
Copy link
Contributor

in a project with a large amount of definitions i would like to be able to not load all of the runtime document nodes upfront unless they're actually being used, and let code-splitting and the bundler just include the ones that are needed.

Hi @jstejada,

The client-preset comes with a Babel plugin to address this concern.
It is not documented yet but you can find a working example here: https://github.com/dotansimha/graphql-code-generator/tree/master/examples/front-end/advanced/babel-optimized

@jstejada
Copy link

@charlypoly oh that’s perfect, thank you!

@jstejada
Copy link

The client-preset comes with a Babel plugin to address this concern.
It is not documented yet but you can find a working example here: https://github.com/dotansimha/graphql-code-generator/tree/master/examples/front-end/advanced/babel-optimized

@charlypoly thanks! i just tried this, but i'm still seeing all of the document nodes being included at runtime on a production build. is there any other configuration required other than the one in the .babelrc.js here?

@charlypoly
Copy link
Contributor

The client-preset comes with a Babel plugin to address this concern.
It is not documented yet but you can find a working example here: master/examples/front-end/advanced/babel-optimized

@charlypoly thanks! i just tried this, but i'm still seeing all of the document nodes being included at runtime on a production build. is there any other configuration required other than the one in the .babelrc.js here?

@jstejada, those document nodes are required for your GraphQL client to work.
The only difference with a graphql-tag is that it is already parsed at compile time and not at runtime.

@jstejada
Copy link

jstejada commented Nov 28, 2022

@jstejada, those document nodes are required for your GraphQL client to work.
The only difference with a graphql-tag is that it is already parsed at compile time and not at runtime.

@charlypoly ah, i see, got it; yeah I understand they are required, my original question was about whether we could avoid loading all runtime document nodes up-front (i.e. since they all get generated into the single generated file), which can be quite a bit in a project with a large number of documents, vs being able to import them only when they are actually being used.

e.g. when visiting a route i would like to only include at runtime the documents used in the query for that route, vs including all the documents defined in the project

this would probably require generating separate files for each document definition, and then having babel transpile into a require/import call to import only that specific file.

in any case, i understand this might not be possible right now, but i'd be curious if there are any extension points in the plugin that might allow me to implement this custom behavior. thanks again for the responses!

@frehner
Copy link

frehner commented Nov 28, 2022

@jstejada, those document nodes are required for your GraphQL client to work.
The only difference with a graphql-tag is that it is already parsed at compile time and not at runtime.

If I have a GraphQL client that only takes in strings, is there a way to get the client preset to compile to strings instead of Document Nodes?

@saihaj
Copy link
Collaborator

saihaj commented Dec 1, 2022

@jstejada, those document nodes are required for your GraphQL client to work.
The only difference with a graphql-tag is that it is already parsed at compile time and not at runtime.

If I have a GraphQL client that only takes in strings, is there a way to get the client preset to compile to strings instead of Document Nodes?

hmm so the client preset uses @graphql-codegen/typed-document-node plugin which doesn't allow the documentMode: string configuration.

if (config && config.documentMode === DocumentMode.string) {
throw new Error(`Plugin "typed-document-node" does not allow using 'documentMode: string' configuration!`);
}

@MH4GF
Copy link

MH4GF commented Jan 21, 2023

Hi everyone, I am excited about the development experience that the client-preset and fragment-masking features will provide!
I'm considering migrating to client-preset from a project already using codegen,
I would like to handle typed-document-node from a .graphql extension file.(This has been mentioned many times in the comments of this issue.)

the client-preset is possible to generate TypedDocumentNode from a .graphql extension file,
and although it is possible to import them at the point of use,
importing from /src/gql/graphql again leads to an increase in file chunks after bundling.

Therefore, it attempts to split the file using the near-operation-file preset.
Even for TypedDocumentNode imported from a split file, type conversion by fragment-masking was possible.

// codegen.ts
import { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
  schema: "https://swapi-graphql.netlify.app/.netlify/functions/index",
  documents: ["src/**/*.graphql"],
  generates: {
    "./src/gql/": {
      preset: "client",
      plugins: [],
    },
    "./src/": {
      preset: "near-operation-file",
      presetConfig: {
        extension: ".generated.ts",
        baseTypesPath: "~~/gql/graphql",
      },
      plugins: ["typed-document-node"],
      config: {
        typesPrefix: "Types.",
      },
    },
  },
};

export default config;
# FilmItem.graphql
fragment FilmItem on Film {
  id
  title
  releaseDate
  producers
}
// FilmItem.generated.ts
import * as Types from '~/gql/graphql';

import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
export const FilmItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FilmItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Film"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"releaseDate"}},{"kind":"Field","name":{"kind":"Name","value":"producers"}}]}}]} as unknown as DocumentNode<Types.FilmItemFragment, unknown>;
// Film.tsx
import { FilmItemFragmentDoc } from "./FilmItem.generated";
import { FragmentType, useFragment } from "./gql/fragment-masking";

const Film = (props: { film: FragmentType<typeof FilmItemFragmentDoc> }) => {
  const film = useFragment(FilmItemFragmentDoc, props.film);
  return (
    <div>
      <h3>{film.title}</h3>
      <p>{film.releaseDate}</p>
    </div>
  );
};

export default Film;

The code for the PoC in progress can be found here: MH4GF/graphql-codegen-client-preset-example@e45ef9a

Is this usage not recommended? Please let me know your thoughts.

@n1ru4l n1ru4l changed the title GraphQL Code Generator v3 Roadmap GraphQL Code Generator v4 Roadmap Feb 1, 2023
@codepunkt
Copy link

Not having nonOptionalTypename on client preset hinders our migration of a large codebase from apollo codegen to this. Have you recently thought about allowing it on client preset?

@n1ru4l
Copy link
Collaborator

n1ru4l commented Feb 3, 2023

@codepunkt As a workaround, you can add __typename selections to your GraphQL operation document selections, apollo will add them anyways before the document is sent to the server.

@codepunkt
Copy link

@n1ru4l Thanks. Turns out it is available but not documented 😀

@productdevbook
Copy link
Contributor

how to nuxt 3 used ?

@ksdenisova
Copy link

Hi team! Was this implemented? I would like to use this in our project

CleanShot 2024-04-09 at 10 36 29@2x

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

No branches or pull requests