Tutorial GraphQL

Yogiokto Agae
Devsaurus Class
Published in
8 min readJan 11, 2021

GraphQL sebagai alternatif REST API

Apa itu GraphQL?

GraphQL adalah bahasa yang digunakan untuk query API.

Sebagian bilang GraphQL bisa menjadi pengganti REST API, tetapi prakteknya GraphQL sering digunakan bersamaan dengan REST API dan bahkan saling melengkapi.

Ada juga yang bilang GraphQL adalah bahasa untuk query database, tetapi sebenarnya GraphQL tidak tahu cara query database karena konsepnya sangat berbeda dengan ORM.

Untuk menggunakannya kita tidak butuh database tertentu. Bahkan kita bisa query dari sebuah file sekalipun.

Yang kita butuhkan hanya mendefinisikan bentuk data yang akan diquery dari sebuah data source. Dan data source ini tidak harus berupa database.

Kata Graph sendiri mewakili jenis struktur data Graph, yaitu jenis struktur data non-linier yang memiliki nodes & edges. Pada GraphQL kita juga akan menemukan nodes & edges.

Data struktur graph adalah salah satu data struktur yang banyak digunakan dalam aplikasi media sosial.

GraphQL diciptakan oleh team engineer Facebook pada tahun 2012 dan menjadi open source project di tahun 2015.

Mungkin saja ini alasan kenapa Facebook menyebutnya GraphQL.

GraphQL vs REST API

Banyak dari kita lebih paham apa itu REST API daripada GraphQL, oleh karena itu di bagian ini kita akan bandingkan antara REST API dengan GraphQL.

HTTP request method

Jika pada REST API ada kita gunakan banyak HTTP request method seperti GET, POST, PUT & DELETE. Pada GraphQL kita hanya menggunakan POST, dengan nama operasi Query & Mutation.

Berikut tabel perbandingan operasi pada REST dengan GraphQL.

Cara Query

Dari gambar diatas, kita bisa lihat bentuk data hasil query dari graphql adalah sesuai dengan field yang diminta.

Berbeda dengan REST API, dimana seringkali kita harus ‘menerima’ data hasil query meskipun ada banyak bagian data yang tidak dibutuhkan.

Untuk mendapatkan data yang memang dibutuhkan dari sebuah REST API kita harus melakukan filtering di sisi client atau membuat endpoint baru.

Dengan GraphQL kita juga bisa menghindari multiple API calls.

Sering kita harus mengirim request ke banyak endpoint untuk mendapatkan data yang kita butuhkan. Pada GraphQL kita hanya perlu memanggil endpoint satu kali, bahkan GraphQL hanya memiliki satu endpoint.

Meskipun tampak jauh lebih simple, tantangan GraphQL ada pada menentukan bentuk GraphQL schema, yaitu bentuk data yang diinginkan.

Konsep Dasar

Kita akan buat sebuah aplikasi sederhana untuk menjelaskan konsep dasar yang ada pada GraphQL.

Persiapan

Pastikan tools berikut ini sudah terinstall:

  • Code Editor (VS Code)
  • Terminal
  • Node.js

GraphQL mendukung banyak bahasa pemrograman, tidak hanya Node.js/JavaScript.

GraphQL Server & GraphQL Client

Pada REST API, posisi sebuah server adalah sebagai API producer dan client sebagai API consumer.

Hal ini juga berlaku untuk GraphQL.

GraphQL Server

Terdapat banyak tool yang bisa digunakan untuk membuat sebuah GraphQL Server, pada tutorial ini kita akan gunakan package express-graphql.

Package express-graphql memungkinkan kita menggunakan graphql pada sebuah aplikasi server express.js.

Buat sebuah folder dengan nama graphql-server kemudian jalankan perintah berikut ini dari terminal untuk inisialisasi sebuah project Node.js

$ yarn init

Kemudian install expressjs, express-graphql & graphql.

$ yarn add express express-graphql graphql

Kemudian buat sebuah file dengan nama server.js.

GraphQL Client

Tools untuk client juga cukup banyak. Tapi untuk tutorial ini kita cukup menggunakan GraphQL in browser IDE bernama GraphiQL.

Schema

Hal pertama yang kita lakukan setelah membuat GraphQL server dan menentukan GraphQL client adalah membuat sebuah schema.

Schema adalah adalah bagaimana bentuk data yang diinginkan didefinisikan.

Sebuah schema terdiri dari satu atau banyak Type. Jenis Type yang banyak digunakan di GraphQL:

  • Object Type
  • Scalar Type
  • Query Type
  • Mutation Type
  • Input Type

Selain yang disebutkan diatas masih ada Enum Type, Interface & Union Type.

Kita buat sebuah schema dengan type Query:

type Query {
id: ID!,
name: String!,
email: String!,
}

Query adalah type khusus pada GraphQL yang mewakili data yang bisa diquery. Jika menggunakan selain Query data tidak akan bisa diquery.

Sehingga pada contoh diatas kita bisa query data id, name & email.

String adalah Scalar type, mirip dengan primitive type pada bahasa pemrograman seperti JavaScript.

Tambahan ! pada Scalar type menunjukan kalo data bersifat non-nullable atau tidak boleh kosong.

Implementasi schema pada server.js:

const { buildSchema } = require("graphql");const schema = buildSchema(`
type Query {
id: ID!,
name: String!,
email: String!,
}
`);

Resolver

Kita sudah menentukan schema, lalu bagaimana dengan datanya?

Data source pada GraphQL bisa berupa sebuah database, file json atau primitive type (string, number dll).

Untuk mengambil atau generate data kita gunakan function yang biasa disebut dengan resolver.

Resolver adalah kumpulan function yang akan memberi response untuk setiap query GraphQL. Response ini dapat berasal dari database atau sebuah string.

Kita buat sebuah resolver pada file server.js untuk generate data name & email:

...
const root = {
name: () => {
return "brachio";
},
email: () => {
return "brachio@email.com";
},
};

Kita beri nama root karena ini akan menjadi root value / initial value / nilai awal. Tetapi kita bebas memilih nama resolver.

Selanjutnya lengkapi code dari server.js menjadi seperti ini agar kita bisa menjalankan server:

const express = require("express");
const { graphqlHTTP } = require("express-graphql");
const { buildSchema } = require("graphql");
const schema = buildSchema(`
type Query {
name: String!,
email: String!,
}
`);
const root = {
name: () => {
return "brachio";
},
email: () => {
return "brachio@email.com";
},
};
const app = express();app.use(
"/graphql",
graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
})
);
app.listen(5000);console.log("Running a GraphQL API server at http://localhost:5000/graphql");

Jalankan server dengan perintah:

node server.js

Setelah server aktif, akses alamat server yaitu http://localhost:5000/graphql.

Kita akan mendapati tampilan GraphQL in browser IDE atau GraphiQL yang akan kita gunakan untuk membuat query.

Query

Untuk query data tulis query seperti ini pada GraphiQL:

{
name
email
}

Kemudian klik pada icon Start / Run.

Hasilnya:

Jika ingin query data email saja, kita tinggal update query menjadi seperti ini:

Mutation

Pada GraphQL jika kita ingin menambah atau update data di server kita gunakan operasi Mutation.

Langkah-langkahnya sebagai berikut…

Kita buat Object type dengan nama User daninput type dengan nama UserInput:

type User {
id: ID!,
name: String!,
email: String!
}
input UserInput {
name: String!,
email: String!
}

Kemudian update Querytype:

type Query {
getUser: User
}

Field getUser digunakan untuk query semua data dalam bentuk Usertype.

Tambahkan Mutationtype:

type Mutation {
createUser(input: UserInput): User
updateUser(id: ID!, input: UserInput): User
}

Untuk Mutationtype kita buat dua field createUser& updateUser.

  • createUser , untuk menambahkan user baru. Menerima input (argument) dalam bentuk UserInput
  • updateUser , untuk update data user. Menerima input (argument) dalam bentuk UserInput dan ID .

Kita akan gunakan sebuah array untuk menyimpan data user.

let users = [{ id, name: "brachio", email: "brachio@email.com" }];

Gunakan crypto, _built-in_ module dari Node.js untuk generate id.

const id = require("crypto").randomBytes(10).toString("hex");let users = [{ id, name: "brachio", email: "brachio@email.com" }];

Tambahkan resolver:

  • getUser
getUser: () => {
return users;
},
  • createUser
createUser: ({ input }) => {
const id = require("crypto").randomBytes(10).toString("hex");
users.push({ id, ...input });
return { id, ...input };
}
  • updateUser
updateUser: ({ id, input }) => {
const newUsers = users.map((user) => {
if (user.id === id) {
return { ...user, ...input };
} else {
return user;
}
});
users = [...newUsers]; return { id, ...input };
}

Final Code:

const express = require("express");
const { graphqlHTTP } = require("express-graphql");
const { buildSchema } = require("graphql");
const schema = buildSchema(`
type User {
id: ID!,
name: String!,
email: String!,
}
input UserInput {
name: String!,
email: String!
}
type Query {
getUser: [User!]!
}
type Mutation {
createUser(input: UserInput): User
updateUser(id: ID!, input: UserInput): User
}
`);
const id = require("crypto").randomBytes(10).toString("hex");let users = [{ id, name: "brachio", email: "brachio@email.com" }];const root = {
getUser: () => {
return users;
},
createUser: ({ input }) => {
const id = require("crypto").randomBytes(10).toString("hex");
users.push({ id, ...input });
return { id, ...input };
},
updateUser: ({ id, input }) => {
const newUsers = users.map((user) => {
if (user.id === id) {
return { ...user, ...input };
} else {
return user;
}
});
users = [...newUsers];return { id, ...input };
},
};
const app = express();app.use(
"/graphql",
graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
})
);
app.listen(5000);console.log("Running a GraphQL API server at http://localhost:5000/graphql");

Sekarang kita coba hasilnya menggunakan GraphiQL:

  • Menambah user
  • Cek data user setelah user baru ditambahkan
  • update existing user

Variables

GraphQL mendukung penggunaan variable dalam query:

Untuk membuat variable yang harus kita lakukan:

  • Deklarasi variable pada query
mutation addUser($input: UserInput) {
...
  • Tulis nilai variable dalam format JSON
{
"input": {
"name": "t-rex",
"email": "t-rex@email.com"
}
}

Pada GraphiQL kita bisa gunakan opsi Query Variables, sedangkan pada client kita harus tulis secara terpisah di dalam sebuah variable atau file json.

  • Gunakan variable dalam query/mutation
...
createUser(input: $input) {
id
}
...

Selain variable, terdapat alias, fragment & directives yang bisa kita pakai untuk membuat query yang lebih kompleks.

Untuk demonya kita perlu update Query type di server.js agar bisa menerima argument:

...
type Query {
getAllUser: [User!]!
getUser(id: ID!): User
}
...

Kemudian update resolver:

...
getAllUser: () => {
return users;
},
getUser: ({id}) => {
const found = users.find(user => user.id === id);
if(!found) {
throw new Error('please check the user id, we cannot find it');
}
return found;
},
...

Alias

Dengan menggunakan alias kita bisa buat beberapa query dengan argument yang berbeda sekaligus:

firstUser & secondUseradalah alias.

Fragment

Dengan fragment kita bisa menulis query sekali untuk digunakan berkali-kali.

Directives

Dengan directives kita bisa menambahkan kriteria pada query.

Misalnya kita gunakan directives @include untuk memfilter data namesaat query. Dimana jika nilainya true maka name dimunculkan dan sebaliknya.

Summary

  • GraphQL adalah bahasa yang digunakan untuk query API.
  • GraphQL Schema adalah definisi dari bentuk data yang diinginkan. Yang berisi satu atau banyak Type.
  • Jenis type GraphQL yang sering digunakan: Object Type, Scalar Type, Query Type, Mutation Type, Input Type
  • Dua operasi yang ada di GraphQL: Query & Mutation, Query untuk mendapatkan data, sedangkan Mutation untuk mengubah data
  • Untuk bisa membuat query atau mutation yang kompleks kita bisa gunakan Argument, Variables, Alias, Fragment & Directives

Semoga tutorial ini bermanfaat. Terima Kasih.

Download full chapter eBook Full Stack Gate, kumpulan materi pendahuluan untuk memulai karir sebagai Full Stack Web Developer disini.

--

--