Typescript Apollo Next.js

Package nameWeekly DownloadsVersionLicenseUpdated
graphql-codegen-apollo-next-ssrDownloadsVersionLicenseJul 11th, 2022

Installation

npm i -D graphql-codegen-apollo-next-ssr
⚠️

Usage Requirements In order to use this GraphQL Codegen plugin, please make sure that you have GraphQL operations (query / mutation / subscription and fragment) set as documents: … in your codegen.yml.

Without loading your GraphQL operations (query, mutation, subscription and fragment), you won’t see any change in the generated output.

⚠ Maintaner needed ⚠

An alternative solution based on swr and gql-request can be found here

graphql-codegen-apollo-next-ssr

Generate apollo code for nextjs ssr

Motivations

Nextjs recently introduced getServerSideProps which doesn’t allow to use the HOC pattern adopted by the official apollo graphql plugin (based on getInitialProps). At the same time the SSR method offered by apollo client (getDataFromTree ) enforces the react app to render multiple times in order to collect and fetch all the relevant queries. By declaring a top level query we can save rendering time and provide a simpler pattern which works with getServerSideProps . This plugin generates a typesafe version of getServerSideProps for each server query, and the corresponding HOC to wrap the react component returning the cache result. The limitation/advantage of this solution is that all the queries embedded into inner react components are ignored, unless covered by the top level cache.

Configuration

  • excludePatterns (default: null): regexp to exclude operation names
  • excludePatternsOptions (default: ”): regexp flags to exclude operation names
  • reactApolloVersion (default: 2): apollo client version
  • apolloCacheImportFrom (default: apollo-cache-inmemory): apollo-cache-inmemory dependency
  • apolloImportFrom (default: apollo-client v2 or @apollo/client v3): apollo client dependency
  • apolloCacheImportFrom (default: apollo-cache-inmemory v2 or @apollo/client v3): apollo cache client dependency
  • apolloStateKey (default: apolloState): Key used for storing Apollo state
  • withHooks (default: false): Customized the output by enabling/disabling the generated React Hooks.
  • withHOC (default: true): Customized the output by enabling/disabling the HOC.
  • customImports (default: ”): full custom import declaration
  • contextType (default: ‘any’): Contex type passed to getApolloClient
  • contextTypeRequired (default: false): If the context should be required when called from getServerSideProps
  • pre (default: ”): custom code before each function
  • post (default: ”): custom code after each function
  • apolloClientInstanceImport(default: ”): Add apolloClient instance imports
  • replaceQuery (default: false): Replace “query” keyword inside the generated operations
  • replacePage (default: false): Replace “page” keyword inside the generated operations
  • reactImport (default: import type React from ‘react’;): custom react import

Example config

overwrite: true
schema:
    - 'https://myschema/graphql'
documents:
    - 'src/**/*.graphql'
generates:
    src/@types/codegen/graphql.tsx:
        plugins:
            - 'typescript'
            - 'typescript-operations'
            - 'typescript-react-apollo'
    src/@types/codegen/page.tsx:
        config:
            documentMode: external
            importDocumentNodeExternallyFrom: ./graphql
        preset: import-types
        presetConfig:
            typesPath: ./graphql
        plugins:
            - ./build/src/index.js
hooks:
    afterAllFileWrite:
        - prettier --write

This plugin generates:

  • a function running an ApolloClient query and cache extraction, to be used inside getServerSideProps or getStaticProps
  • a React Apollo HOC running an ApolloClient query consuming the InMemory cache
  • an interface for the React component wrapped by the HOC

It extends the basic TypeScript plugins: @graphql-codegen/typescript, @graphql-codegen/typescript-operations - and thus shares a similar configuration.

Motivations

Next.js recently introduced getServerSideProps and getStaticProps which doesn’t allow to use the HOC pattern adopted by the official apollo graphql plugin (based on getInitialProps). At the same time the SSR method offered by apollo client (getDataFromTree) enforces the React app to render multiple times in order to collect and fetch all the relevant queries. By declaring a top level query we can save rendering time and provide a simpler pattern which works with getServerSideProps. Note that this pattern requires each SSR query to run at top level. Example

API Reference

apolloReactCommonImportFrom

type: string default: "

Customize the package where apollo-react common lib is loaded from.

apolloImportFrom

type: string default: "

Customize the package where apollo-client lib is loaded from.

apolloCacheImportFrom

type: string default: "

Customize the package where apollo-cache-inmemory lib is loaded from.

apolloReactHooksImportFrom

type: string default: "

Customize the package where apollo-react hooks lib is loaded from.

reactApolloVersion

type: number (values: 2, 3) default: 2

Sets the version of react-apollo.

Usage Examples

codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file.ts': {
      plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
      config: {
        reactApolloVersion: 3
      }
    }
  }
}
export default config

withHOC

type: boolean default: true

Customized the output by enabling/disabling the HOC.

Usage Examples

codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file.ts': {
      plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
      config: {
        withHOC: 'I'
      }
    }
  }
}
export default config

withHooks

type: boolean default: false

Customized the output by enabling/disabling the generated React Hooks.

Usage Examples

codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file.ts': {
      plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
      config: {
        withHooks: 'I'
      }
    }
  }
}
export default config

excludePatterns

type: string default: ''

Regexp to exclude a certain operation name.

excludePatternsOptions

type: string default: ''

Regexp options to exclude a certain operation name.

pre

type: string default: ''

Add custom code before each operation.

post

type: string default: ''

Add custom code after each operation.

customImports

type: string default: ''

Add custom imports needed by pre/post.

gqlImport

type: string default: gql#graphql-tag

Customize from which module will gql be imported from. This is useful if you want to use modules other than graphql-tag, e.g. graphql.macro.

Usage Examples

graphql.macro
codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file.ts': {
      plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
      config: {
        gqlImport: 'graphql.macro#gql'
      }
    }
  }
}
export default config
Gatsby
codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file.ts': {
      plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
      config: {
        gqlImport: 'gatsby#graphql'
      }
    }
  }
}
export default config

noExport

type: boolean default: false

Set this configuration to true if you wish to tell codegen to generate code with no export identifier.

dedupeOperationSuffix

type: boolean default: false

Set this configuration to true if you wish to make sure to remove duplicate operation name suffix.

omitOperationSuffix

type: boolean default: false

Set this configuration to true if you wish to disable auto add suffix of operation name, like Query, Mutation, Subscription, Fragment.

operationResultSuffix

type: string default: “

Adds a suffix to generated operation result type names

documentVariablePrefix

type: string default: “

Changes the GraphQL operations variables prefix.

documentVariableSuffix

type: string default: Document

Changes the GraphQL operations variables suffix.

fragmentVariablePrefix

type: string default: “

Changes the GraphQL fragments variables prefix.

fragmentVariableSuffix

type: string default: FragmentDoc

Changes the GraphQL fragments variables suffix.

documentMode

type: DocumentMode default: graphQLTag

Declares how DocumentNode are created:

  • graphQLTag: graphql-tag or other modules (check gqlImport) will be used to generate document nodes. If this is used, document nodes are generated on client side i.e. the module used to generate this will be shipped to the client
  • documentNode: document nodes will be generated as objects when we generate the templates.
  • documentNodeImportFragments: Similar to documentNode except it imports external fragments instead of embedding them.
  • external: document nodes are imported from an external file. To be used with importDocumentNodeExternallyFrom

importOperationTypesFrom

type: string default: “

This config is used internally by presets, but you can use it manually to tell codegen to prefix all base types that it’s using. This is useful if you wish to generate base types from typescript-operations plugin into a different file, and import it from there.

importDocumentNodeExternallyFrom

type: string default: “

This config should be used if documentMode is external. This has 2 usage:

  • any string: This would be the path to import document nodes from. This can be used if we want to manually create the document nodes e.g. Use graphql-tag in a separate file and export the generated document
  • ‘near-operation-file’: This is a special mode that is intended to be used with near-operation-file preset to import document nodes from those files. If these files are .graphql files, we make use of webpack loader.

Usage Examples

codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file': {
      // plugins...
      config: {
        documentMode: 'external',
        importDocumentNodeExternallyFrom: 'path/to/document-node-file'
      }
    }
  }
}
export default config
codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file': {
      // plugins...
      config: {
        documentMode: 'external',
        importDocumentNodeExternallyFrom: 'near-operation-file'
      }
    }
  }
}
export default config

scalars

type: ScalarsMap

Extends or overrides the built-in scalars and custom GraphQL scalars to a custom type.

Usage Examples

codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file': {
      // plugins...
      config: {
        scalars: {
          DateTime: 'Date',
          JSON: '{ [key: string]: any }'
        }
      }
    }
  }
}
export default config

namingConvention

type: NamingConvention default: change-case-all#pascalCase

Allow you to override the naming convention of the output. You can either override all namings, or specify an object with specific custom naming convention per output. The format of the converter must be a valid module#method. Allowed values for specific output are: typeNames, enumValues. You can also use “keep” to keep all GraphQL names as-is. Additionally, you can set transformUnderscore to true if you want to override the default behavior, which is to preserve underscores.

Usage Examples

Override All Names
codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file': {
      // plugins...
      config: {
        namingConvention: 'change-case-all#lowerCase'
      }
    }
  }
}
export default config
Upper-case enum values
codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file': {
      // plugins...
      config: {
        namingConvention: {
          typeNames: 'change-case-all#pascalCase',
          enumValues: 'change-case-all#upperCase'
        }
      }
    }
  }
}
export default config
Keep names as is
codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file': {
      // plugins...
      config: {
        namingConvention: 'keep'
      }
    }
  }
}
export default config
Remove Underscores
codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file': {
      // plugins...
      config: {
        namingConvention: {
          typeNames: 'change-case-all#pascalCase',
          transformUnderscore: true
        }
      }
    }
  }
}
export default config

typesPrefix

type: string default: “

Prefixes all the generated types.

Usage Examples

codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file.ts': {
      plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
      config: {
        typesPrefix: 'I'
      }
    }
  }
}
export default config

skipTypename

type: boolean default: false

Does not add __typename to the generated types, unless it was specified in the selection set.

Usage Examples

codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file.ts': {
      plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
      config: {
        skipTypename: true
      }
    }
  }
}
export default config

nonOptionalTypename

type: boolean default: false

Automatically adds __typename field to the generated types, even when they are not specified in the selection set, and makes it non-optional.

Usage Examples

codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'
 
const config: CodegenConfig = {
  // ...
  generates: {
    'path/to/file.ts': {
      plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
      config: {
        nonOptionalTypename: true
      }
    }
  }
}
export default config