GraphQL Codegen dipakai untuk mengurangi mismatch antara schema GraphQL dengan kode aplikasi. Alih-alih menulis type secara manual dan berharap query tetap valid, Anda bisa menghasilkan type, typed operations, dan helper client langsung dari schema dan dokumen GraphQL yang benar-benar dipakai aplikasi.
Masalah yang sering terjadi di tim adalah schema berubah tanpa update client, type manual menjadi usang, atau pull request lolos review padahal query sudah tidak valid. Dengan GraphQL Code Generator, kontrak API bisa divalidasi lebih awal di lokal maupun CI, sehingga error berpindah dari runtime ke build time.
Mengapa GraphQL Codegen penting untuk workflow tim
GraphQL memang memberi fleksibilitas tinggi, tetapi fleksibilitas itu juga membuka ruang inkonsistensi jika tidak ada proses validasi yang ketat. Beberapa masalah umum:
- Schema drift: backend mengubah field, argumen, atau nullability, tetapi frontend belum menyesuaikan.
- Type manual usang: interface TypeScript ditulis tangan dan tidak lagi merepresentasikan hasil query sebenarnya.
- Query invalid lolos review: reviewer fokus pada logic aplikasi, bukan validitas query terhadap schema terbaru.
- DX buruk: autocomplete lemah, rename field berisiko, dan refactor membutuhkan pengecekan manual.
Codegen bekerja baik karena ia membaca dua sumber kebenaran sekaligus: schema GraphQL dan documents (query, mutation, subscription, fragment). Dari situ, generator dapat memastikan bahwa hanya field yang valid yang dipakai, dan output type mengikuti bentuk response aktual, bukan perkiraan developer.
Output apa saja yang biasanya dihasilkan
Dalam praktik, tim biasanya memakai GraphQL Code Generator untuk tiga keluaran utama:
1. Type schema dasar
Type ini merepresentasikan scalar, object, input, enum, dan utilitas umum dari schema. Berguna jika Anda butuh referensi type GraphQL secara langsung di TypeScript.
2. Typed operations
Ini yang paling penting untuk frontend. Setiap query atau mutation menghasilkan type untuk variables dan response. Jadi jika query GetUser meminta field tertentu, type hasilnya akan tepat mengikuti field yang benar-benar diminta.
3. Helper client
Tergantung stack, codegen bisa menghasilkan helper agar integrasi dengan client library lebih aman. Misalnya dokumen bertipe, helper request, atau artefak yang lebih mudah dipakai oleh Apollo Client, urql, graphql-request, atau client lain.
Prinsip pentingnya: jangan mengandalkan type global schema untuk response UI. Response query GraphQL sering kali hanya subset dari schema. Yang paling aman adalah type hasil operasi yang benar-benar dipakai.
Struktur file yang rapi untuk adopsi jangka panjang
Struktur file bukan aturan wajib, tetapi struktur yang konsisten mempermudah adopsi tim dan integrasi CI. Contoh yang umum:
src/
graphql/
fragments/
userFields.graphql
queries/
getUser.graphql
mutations/
updateUser.graphql
generated/
graphql.ts
schema.graphql
codegen.yml
Alternatif lain adalah menaruh query dekat komponen atau feature, misalnya pola colocation:
src/
features/
user/
UserProfile.tsx
UserProfile.graphql
UserProfile.test.ts
generated/
graphql.ts
codegen.yml
Pilih pendekatan berdasarkan kebutuhan tim:
- Folder terpusat cocok jika tim ingin audit query lebih mudah.
- Colocation cocok jika ingin query dekat dengan komponen yang memakainya.
Yang penting, path dokumen di config codegen harus stabil dan mudah dipahami semua anggota tim.
Contoh konfigurasi dasar GraphQL Codegen
Konfigurasi bisa ditulis dalam YAML atau file JavaScript/TypeScript, tergantung kebutuhan. Untuk contoh yang sederhana, anggap schema tersedia dari endpoint atau file introspection/schema SDL, dan dokumen GraphQL berada di dalam src.
schema: ./schema.graphql
documents:
- ./src/**/*.graphql
generates:
./src/generated/graphql.ts:
plugins:
- typescript
- typescript-operations
- typed-document-node
Apa fungsi tiap bagian:
schema: sumber schema GraphQL. Bisa file lokal atau endpoint remote.documents: lokasi query, mutation, subscription, dan fragment yang dipakai aplikasi.typescript: menghasilkan type dasar dari schema.typescript-operations: menghasilkan type untuk hasil operasi dan variables.typed-document-node: menghasilkan dokumen GraphQL bertipe sehingga client lebih aman saat dipakai di TypeScript.
Konfigurasi ini cukup sebagai baseline untuk banyak proyek TypeScript. Jika aplikasi Anda menggunakan client tertentu, Anda bisa menambah plugin yang relevan, tetapi jangan mulai terlalu kompleks. Mulai dari typed operations dulu, lalu tambahkan helper spesifik stack bila memang berguna.
Integrasi dengan TypeScript: dari string query ke dokumen bertipe
Misalkan ada query berikut:
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
Setelah generate, Anda biasanya akan mendapatkan artefak TypeScript yang setara dengan:
export type GetUserQueryVariables = {
id: string;
};
export type GetUserQuery = {
user?: {
id: string;
name: string;
email: string;
} | null;
};
Jika memakai typed document, Anda bisa menggunakannya di client tanpa cast manual. Contoh umum:
import { client } from './client';
import { GetUserDocument } from './generated/graphql';
const result = await client.request(GetUserDocument, { id: '123' });
Mengapa ini lebih aman dibanding string biasa?
- Variables divalidasi oleh TypeScript.
- Response mengikuti shape query aktual, bukan seluruh type schema.
- Jika field dihapus dari schema, proses generate atau type-check biasanya langsung gagal.
Ini meningkatkan developer experience saat refactor. Rename field atau perubahan nullability akan cepat terlihat sebagai error kompilasi, bukan bug tersembunyi di runtime.
Validasi dokumen query agar error muncul lebih awal
Salah satu manfaat terbesar GraphQL Codegen adalah validasi dokumen terhadap schema. Query berikut misalnya akan gagal jika field fullName tidak ada di type User:
query GetUser($id: ID!) {
user(id: $id) {
id
fullName
}
}
Tanpa validasi otomatis, query invalid seperti ini bisa lolos code review, terutama jika perubahan terjadi di branch lain dan reviewer tidak menyadari schema terbaru. Dengan codegen di lokal dan CI, kesalahan menjadi lebih cepat terlihat.
Supaya validasi efektif:
- Simpan operasi GraphQL sebagai file
.graphqlatau gunakan pola yang bisa dipindai codegen secara konsisten. - Pastikan semua fragment ikut tercakup di path
documents. - Jalankan generate atau check sebagai bagian dari alur development, bukan hanya sesekali.
Menjaga schema tetap sinkron dengan frontend dan backend
Kontrak GraphQL tidak hanya soal query. Sumber schema juga harus terkelola dengan jelas. Ada dua pola umum:
Schema dari file lokal
Cocok jika backend dan frontend berada di monorepo, atau schema diekspor ke repository yang sama. Keuntungannya lebih deterministik di CI karena build tidak bergantung pada endpoint jaringan.
Schema dari endpoint remote
Cocok jika frontend dan backend dipisah. Namun Anda perlu strategi agar CI tidak rapuh karena ketergantungan jaringan, autentikasi, atau environment yang tidak stabil.
Jika memungkinkan, simpan snapshot schema di repository frontend atau generate schema artefact secara terjadwal. Dengan begitu, perubahan schema menjadi bagian dari diff yang bisa direview, bukan perubahan implisit yang baru terasa saat runtime.
Untuk tim yang ingin review lebih ketat, perlakukan perubahan schema seperti perubahan kontrak publik. Jangan hanya mengandalkan deploy backend berhasil.
Menjalankan generate di lokal
Di lokal, tujuan utamanya adalah memberi feedback secepat mungkin. Workflow yang umum:
- Perbarui schema jika sumbernya berasal dari backend atau artefak terpisah.
- Tulis atau ubah query/mutation/fragment.
- Jalankan codegen.
- Perbaiki error validasi jika ada.
- Lanjutkan type-check dan test aplikasi.
Contoh skrip yang lazim di package.json:
{
"scripts": {
"graphql:generate": "graphql-codegen",
"graphql:check": "graphql-codegen --errors-only",
"typecheck": "tsc --noEmit"
}
}
Nama skrip bisa berbeda sesuai preferensi tim. Intinya, bedakan antara:
- generate: menghasilkan file output.
- check: memvalidasi dan gagal jika ada error.
Untuk DX yang lebih baik, beberapa tim menjalankan mode watch saat mengembangkan fitur yang banyak menyentuh query. Namun hati-hati agar file generated tidak terlalu sering memicu rebuild berantai jika tooling proyek sensitif terhadap perubahan file.
Integrasi CI untuk mencegah PR yang tidak sinkron
CI adalah tempat terbaik untuk memastikan kontrak GraphQL benar-benar konsisten. Minimal, pipeline pull request perlu memeriksa tiga hal:
- Schema bisa dibaca.
- Semua dokumen GraphQL valid terhadap schema.
- Artefak generated up to date dan tidak tertinggal dari perubahan source.
Contoh urutan job yang praktis:
1. install dependencies
2. fetch atau siapkan schema
3. jalankan graphql:generate atau graphql:check
4. jalankan typecheck
5. verifikasi tidak ada perubahan file generated yang belum di-commit
Poin kelima penting jika repository Anda menyimpan file generated. Tujuannya agar PR gagal ketika developer mengubah query tetapi lupa menjalankan generate sebelum commit.
Ada dua pendekatan utama:
Menyimpan file generated di repository
Kelebihan:
- Build lokal lebih cepat untuk anggota tim yang baru clone.
- Diff generated bisa direview saat kontrak berubah.
- CI bisa memeriksa apakah hasil generate konsisten.
Kekurangan:
- Menambah noise pada diff.
- Potensi conflict merge lebih tinggi.
Tidak menyimpan file generated
Kelebihan:
- Repository lebih bersih.
- Mengurangi conflict pada file artefak.
Kekurangan:
- Semua environment harus selalu menjalankan generate sebelum build.
- Error karena generate terlewat lebih mudah terjadi jika pipeline tidak disiplin.
Jika tim Anda masih awal mengadopsi codegen, menyimpan artefak generated sering lebih mudah karena alur review menjadi eksplisit.
Cek schema drift saat pull request
Schema drift terjadi ketika frontend memvalidasi terhadap schema lama, padahal backend sudah berubah. Ini sering menimbulkan dua jenis masalah:
- PR frontend terlihat hijau, tetapi gagal setelah merge karena schema target branch berbeda.
- PR backend menghapus field tanpa ada sinyal jelas bahwa client aktif masih memakainya.
Beberapa praktik yang membantu:
1. Jadikan schema artefact bagian dari perubahan backend
Jika backend dan frontend berada dalam satu monorepo, update schema bersamaan dengan perubahan resolver/type. Frontend lalu memvalidasi langsung terhadap artefak itu.
2. Validasi frontend terhadap schema dari branch target
Di CI, pastikan frontend tidak hanya memakai cache schema lama. Ia harus mengambil schema yang relevan dengan kondisi branch target atau artefak terbaru yang disepakati tim.
3. Tambahkan pemeriksaan breaking change di level backend
Codegen di frontend membantu mendeteksi query invalid, tetapi tidak selalu cukup untuk memberi daftar semua client yang terdampak. Jika organisasi Anda besar, pertimbangkan pemeriksaan breaking change schema sebagai langkah terpisah di pipeline backend.
Intinya, codegen menyelesaikan sebagian besar masalah sinkronisasi harian, tetapi disiplin sumber schema tetap menentukan kualitas hasilnya.
Contoh workflow implementasi bertahap
Jika proyek Anda saat ini masih memakai type manual, jangan migrasi semuanya sekaligus. Pendekatan bertahap biasanya lebih aman:
Tahap 1: validasi query dulu
- Tambahkan GraphQL Codegen dengan
schemadandocuments. - Generate typed operations untuk sebagian query yang paling aktif diubah.
- Biarkan type manual lama tetap ada sementara.
Tahap 2: migrasikan integrasi client
- Ubah pemanggilan request agar memakai dokumen bertipe.
- Kurangi cast seperti
as SomeTypepada hasil response. - Mulai ganti interface manual dengan type hasil codegen.
Tahap 3: masukkan ke CI
- Tambahkan job validasi GraphQL pada setiap pull request.
- Gagalkan build jika query invalid atau generated file ketinggalan.
- Gabungkan dengan
typecheckagar perubahan schema langsung terlihat efeknya di aplikasi.
Tahap 4: rapikan struktur dan aturan tim
- Standarkan lokasi file
.graphql. - Tetapkan apakah generated file disimpan di repo atau tidak.
- Tulis panduan singkat untuk update schema, generate, dan review diff.
Masalah umum dan cara debugging
Dokumen tidak terdeteksi
Biasanya masalah ada pada glob documents yang salah atau file query berada di lokasi yang tidak tercakup. Periksa path relatif dari file config dan pastikan ekstensi file sesuai.
Fragment hilang atau tidak dikenal
Pastikan semua file fragment ikut masuk ke pola documents. Jika sebagian query ditulis inline dan sebagian di file terpisah, inkonsistensi path mudah menyebabkan fragment tidak terbaca.
Schema remote gagal di CI
Masalah umum: token tidak ada, endpoint tidak bisa diakses, atau environment CI tidak punya jaringan ke service internal. Solusi yang sering lebih stabil adalah memakai schema artefact lokal untuk proses generate.
Type nullability terasa membingungkan
Ini biasanya bukan bug codegen, melainkan konsekuensi dari schema GraphQL. Jika sebuah field nullable, TypeScript hasil generate juga harus mengakomodasi null atau undefined sesuai output plugin. Jangan menutupi ini dengan cast paksa; lebih baik tangani state null secara eksplisit di kode aplikasi.
Generated file terlalu besar
Sering terjadi jika semua operasi dan schema digabung ke satu file besar. Anda bisa mempertimbangkan pemisahan output berdasarkan kebutuhan proyek, tetapi lakukan hanya jika ukuran file mulai mengganggu build, review, atau performa editor.
Review PR jadi penuh noise
Jika menyimpan generated file di repo, biasakan reviewer fokus pada dua hal: perubahan dokumen GraphQL dan apakah diff generated masuk akal. Untuk mengurangi noise, jaga agar output stabil dan hindari perubahan formatting yang tidak perlu.
Kesalahan adopsi yang sering terjadi
- Masih menulis type response manual meskipun typed operations sudah tersedia.
- Tidak memvalidasi di CI, sehingga manfaat codegen hanya terasa di mesin developer tertentu.
- Schema tidak jelas sumbernya, membuat hasil generate berbeda antara lokal dan CI.
- Mencampur query string acak di banyak file tanpa pola dokumen yang konsisten.
- Menambah plugin terlalu banyak di awal sebelum tim paham alur dasar generate dan validasi.
Mulailah dari kebutuhan inti: validasi dokumen dan type hasil operasi. Setelah itu baru optimalkan integrasi lanjutan sesuai client library dan arsitektur proyek.
Checklist adopsi GraphQL Codegen
- Tentukan sumber schema: file lokal atau endpoint remote.
- Tentukan lokasi dokumen GraphQL dan konsistenkan strukturnya.
- Tambahkan config dasar dengan plugin
typescript,typescript-operations, dantyped-document-node. - Buat skrip lokal untuk generate dan check.
- Integrasikan typed documents ke client TypeScript.
- Kurangi interface manual untuk response GraphQL.
- Tambahkan validasi GraphQL ke pipeline pull request.
- Putuskan apakah file generated disimpan di repository.
- Dokumentasikan alur update schema dan regenerasi artefak.
- Audit query lama yang belum tervalidasi dan migrasikan bertahap.
Penutup
GraphQL Codegen untuk type safety dan CI yang konsisten bukan sekadar alat pembuat type. Ia adalah mekanisme untuk menjaga kontrak schema tetap sinkron dengan query dan kode aplikasi, sekaligus memindahkan banyak error dari runtime ke tahap build.
Jika diterapkan dengan struktur file yang jelas, config dasar yang sederhana, dan validasi di CI, tim akan lebih cepat mendeteksi schema drift, query invalid, dan type manual yang usang. Hasil akhirnya bukan hanya TypeScript yang lebih rapi, tetapi workflow review dan deploy yang lebih dapat dipercaya.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!