A webpack loader to import type-protected codegen results directly from GraphQL documents.
Try the Next.js example that integrates graphql-let.
One of the strengths of GraphQL is enforcing data types on runtime. Further, TypeScript and GraphQL Code Generator (graphql-codegen) make it safer by typing data statically, so you can write truly type-protected code with rich IDE assists.
To enhance the development pattern, it's necessary to focus on a more specific use-case than what graphql-codegen allows; binding TypeScript (and assuming the use of Apollo-Client and React). In the way, graphql-let behaves as a subset of graphql-codegen.
graphql-let lets you import graphql-codegen results directly per GraphQL documents with TypeScript type definitions by webpack Loader power.
import { useNewsQuery } from './news.graphql'
const News: React.FC = () => {
// Typed already️⚡️
const { data: { news } } = useNewsQuery()
if (news) return <div>{news.map(...)}</div>
}
Two things:
- It runs graphql-codegen inside according to the
.graphql-let.yml
and pass the generated TypeScript source to the next loader. - It generates a file
.d.ts
.
You may also want only .d.ts
before a webpack build to check types. Run
graphql-let
command to get .d.ts
without running webpack.
This is an example of TypeScript + React + Apollo Client. Please replace the corresponding lines depending on your needs.
Note graphql-let is devDependencies
.
npm install -D graphql-let @graphql-codegen/cli @graphql-codegen/plugin-helpers @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo
npm install @apollo/react-common @apollo/react-components @apollo/react-hooks
Run this command to have a configuration template.
npx graphql-let init
# This will generate .graphql-let.yml
Next add graphql-codegen plugins in it. Please note that you have to generate TypeScript source by the plugins.
Edit it like this:
schema: lib/type-defs.graphqls
documents: '**/*.graphql'
plugins:
- typescript
+ - typescript-operations
+ - typescript-react-apollo
Available options:
property | required | type | meaning | examples |
---|---|---|---|---|
schema |
✔︎ | string |
The GraphQL schema info that graphql-let requests introspection to. |
|
documents |
✔︎ | string | string[] |
The GraphQL documents info of quereis and mutations etc. All the documents have to be separate files. | ./queries-and-mutations/**/*.graphql |
plugins |
✔︎ | string[] |
The plugin names of graphql-codegen. |
|
respectGitIgnore |
✔︎ | boolean |
Whether to use .gitignore to ignore like node_modules . It's passed to globby internally. |
true |
config |
Record<string, boolean | string> |
The configuration for the plugins. more info | These are configured by default.
|
graphql-let will generate .d.ts
files in the same folder of .graphql
. Add
these lines in your .gitignore.
+*.graphql.d.ts
+*.graphqls.d.ts
The webpack loader also needs to be configured. Note that the content that
graphql-let/loader
generates is JSX-TypeScript. You have to compile it to
JavaScript with an additional loader such as babel-loader
.
const config: Configuration = {
module: {
rules: [
+ {
+ test: /\.graphql$/,
+ use: [
+ { loader: 'babel-loader', options: { presets: ['@babel/preset-typescript', '@babel/preset-react'] } },
+ { loader: 'graphql-let/loader' },
+ ]
+ }
]
}
}
Run this to generate .d.ts
.
npx graphql-let
# This will generate files such as:
# - src/query.graphql.d.ts
# - src/schema.graphqls.d.ts
By --config
option you can specify the custom path to the .graphql-let.yml
.
The directory .graphql-let.yml is located at
is the basepath of the relative paths in .grpahql-let.yml. Also, the basepath
should be identical to webpack's config.context
so the loader can find the
config file.
pwd # "/app"
npx graphql-let --config custom/path/.graphql-let.yml
# This will point paths such as:
# /app/custom/path/src/query.graphql.d.ts
# /app/custom/path/src/schema.graphqls.d.ts
You may want to run it everytime calling tsc
. Please check your package.json
and modify like this.
"scripts": {
- "build": "tsc"
+ "build": "graphql-let && tsc"
},
Enjoy HMR (Hot Module Replacement) of webpack with the generated
react-apollo hooks and IDE code assists.
import { useNewsQuery } from './news.graphql'
const News: React.FC = () => {
// Already typed⚡️
const { data: { news } } = useNewsQuery()
if (news) return <div>{ news.map(...) }</div>
}
If:
- your
schema
in .graphql-let.yml points to a single local GraphQL schema file (.graphqls
) - you have installed
@graphql-codegen/typescript-resolvers
in dependencies
, graphql-let will generate .graphqls.d.ts
to help you type your GraphQL
resolvers. Run:
yarn add -D @graphql-codegen/typescript-resolvers
yarn graphql-let
then you will get Resolver
type from the schema file.
import { Resolvers } from "./type-defs.graphqls";
const resolvers: Resolvers = {
Query: {
// All typed⚡️
viewer(parent, args, context, info) {
return { ... }
},
}
};
export default resolvers;
graphql-let/schema/loader
is also available. It just pass GraphQL Content to
the next loader but it updates resolver types in HMR. Set it up as below:
const config: Configuration = {
module: {
rules: [
+ {
+ test: /\.graphqls$/,
+ use: [
+ { loader: 'graphql-tag/loader' },
+ { loader: 'graphql-let/schema/loader' },
+ ]
+ }
]
}
}
Yes.
No. There are
more plugins that also generates .ts
from GraphQL documents.
Afraid not. You need to have separate files to execute the webpack loader.
Besides, typing the value of gql`...`
would be impossible.
Not exactly, but I'd recommend them. I think using different extensions for
schema/documents leads to a more understandable configuration for webpack
loaders with fewer pitfalls. Another reason for .graphqls
is that it's one of
the supported extensions in the internal library.
Query document exports DocumentNode
named ${QueryName}Document
that you can make use of it.
You can't yet. Please watch the progress.
MIT