Penafian: kami tidak menjelaskan secara rinci "esensi ajaib" dan sejarah asal instrumen (banyak yang telah dikatakan tentang ini). Kami berharap mereka yang sudah terbiasa dengan GraphQL akan mendapatkan manfaat dari pengalaman praktis kami.
Kami baru-baru ini mengambil bagian dalam pembuatan katalog peralatan pencahayaan di Internet. Untuk membuat halaman iklan, administrator situs dapat menggunakan perancang: pilih blok yang diperlukan (misalnya, spanduk atau daftar), isi dengan data, tentukan urutan tampilan dan pengaturan lainnya. Pada saat yang sama, aplikasi merender komponen yang telah diatur sebelumnya untuk setiap jenis blok.
Di setiap kategori katalog online, kartu dari berbagai grup produk ditampilkan, dan saat Anda mengarahkan kursor ke kartu, daftar properti untuk produk terlampir ditampilkan.
Kami perlu menampilkan properti produk dalam struktur pohon dan memberikan kecepatan permintaan pemrosesan yang cukup tinggi.
Kami telah memilih urutan pekerjaan berikut dengan permintaan:
- Minta semua grup produk untuk kategori tertentu (biasanya sekitar 50 grup).
- Minta daftar produk untuk setiap grup.
- Minta daftar properti untuk setiap produk.
Karena kami mengembangkan aplikasi berdasarkan GraphQL, kami siap menghadapi kenyataan bahwa beberapa data akan memiliki struktur bersarang yang agak rumit. Meskipun percabangan struktur ini logis untuk pengembangan backend, perlu untuk menulis beberapa logika "ekstra" di bagian depan untuk memproses data dan mengeluarkannya ke komponen, sesuai dengan desain.
Karena sifat dari konstruktor GraphQL, kami memutuskan untuk mengumpulkan properti dan nilai unik bukan di belakang, tetapi di depan, dan kemudian merendernya dalam urutan tertentu. Namun, pemrosesan permintaan terlalu lambat - hingga 20 detik, yang tentu saja tidak cocok untuk kami.
Untuk alasan ini, kami mulai membagi setiap permintaan menjadi subkueri kecil dan memuat data dalam beberapa bagian. Hasilnya, kecepatan aplikasi meningkat secara nyata - permintaan tidak lebih dari 2 detik. Meskipun jumlah permintaan meningkat, beban pada sistem telah berkurang, kebutuhan untuk memuat data yang tidak digunakan telah hilang.
Selanjutnya, mari kita bicara lebih detail secara langsung tentang bekerja dengan GraphQL.
Fitur bekerja dengan GraphQL
Persyaratan produk bagi kami untuk menggunakan bahasa kueri GraphQL yang dikembangkan oleh Facebook. Untuk alasan ini, kami tidak terlibat dalam argumen tanpa akhir tentang mana yang lebih baik, GraphQL atau REST - sebagai gantinya, kami memutuskan untuk menggunakan teknologi yang tepat dengan cara yang paling efisien, dengan mempertimbangkan semua kekuatannya.
Kami memperhitungkan bahwa GraphQL dirancang untuk menyederhanakan pengembangan dan pemeliharaan API, terutama dengan memiliki satu titik akhir.
GET /news
GET /posts
POST /news
POST /post
GraphQL memiliki satu titik akhir. Artinya, kita tidak perlu membuat dua permintaan terpisah untuk mendapatkan data dari dua sumber daya yang berbeda. GraphQL menggabungkan semua permintaan dan mutasi menjadi satu titik akhir dan membuatnya tersedia untuk referensi, serta menghindari pembuatan versi yang melekat di REST API.
GraphQL menyediakan kemampuan untuk mengoptimalkan kinerja dan mendapatkan data persis yang dibutuhkan saat ini menggunakan sintaks kueri khusus: bidang wajib harus dicantumkan dalam kueri.
const FETCH_USER_DATA = gql`
query FetchUserData {
user {
firstName
lastName
date
}
}
`;
GraphQL menggunakan entitas yang sangat diketik dan skema tipe, yang pada gilirannya berguna dalam hubungannya dengan TypeScript dan pembuatan tipe di bagian depan.
Banyak dari fitur-fitur ini tentunya dapat diimplementasikan pada REST API, namun, GraphQL menyediakannya di luar kotak.
Untuk interaksi klien dengan GraphQL, kami memilih solusi paling populer dengan dokumentasi yang bagus - pustaka Apollo Client, yang memungkinkan Anda untuk mendapatkan, menyimpan cache, dan memodifikasi data aplikasi. Apollo Client memberi Anda kemampuan untuk menggunakan pengait dan alat permintaan dan mutasi untuk melacak status unduhan / kesalahan dengan mudah.
Juga di bagian depan, kami menggunakan kerangka kerja NextJS, dipilih dengan mempertimbangkan faktor-faktor berikut: pra-rendering (NextJS menyediakan mekanisme yang sangat sederhana untuk mengimplementasikan pembuatan statis dan SSR di luar kotak), dukungan untuk semua solusi css-in-js yang ada, perutean dinamis, dukungan untuk file statis (misalnya gambar) dalam komponen React.
Akhirnya, setelah teknologi dipilih, mari kita lanjutkan ke pengembangan. Sekilas, semuanya terlihat bagus: perpustakaan modern, dokumentasi bagus, banyak kasus penggunaan berbeda. Masing-masing teknologi dirancang secara individual untuk memfasilitasi pengembangan yang nyaman dan cepat. Dengan membuat boilerplate, yang sangat diperlukan, dan mendesain komponen UI, kami secara bertahap mendekati tahap interaksi yang efektif antara library kami. Di sini semua kesenangan dimulai.
Melihat lebih dalam ke mekanisme NextJS, kita dapat melihat bahwa ia menggunakan dua bentuk pra-render: generasi statis dan SSR. Kedua strategi ini diimplementasikan menggunakan fungsi pramuat data khusus:
`getInitialProps` (SSR) - pada pemuatan pertama, ini berjalan di server, meminta data dan kemudian meneruskannya ke komponen sebagai props.
function Component ({data}) {
...
}
Component.getInitialProps = async (ctx) => {
const res = await fetch('https://...')
const json = await res.json()
return { data: json.data }
}
`getStaticProps` (Generasi Statis) - dijalankan pada tahap pembuatan. NextJS membuat halaman sebelumnya menggunakan props yang dikembalikan dari fungsi ini.
export async function getStaticProps(context) {
return {
props: {}, // props
}
}
`getServerSideProps` (Server Side Rendering) - NextJS merender halaman sebelumnya pada setiap permintaan, menggunakan data yang dikembalikan dari fungsi ini sebagai props.
export async function getServerSideProps(context) {
return {
props: {}, // props
}
}
Jadi, semua fungsi yang terdaftar dideklarasikan di luar komponen, menerima beberapa data dan meneruskannya ke komponen. Ini mengarah ke salah satu masalah interaksi dengan Klien Apollo. Pustaka menyediakan mekanisme kueri seperti hook ʻuseQuery` dan komponen `Query`, dan tidak ada metode yang diusulkan bisa digunakan di luar komponen. Dengan pemikiran ini, dalam proyek kami, kami memutuskan untuk menggunakan pustaka berikutnya-dengan-apollo dan pada akhirnya kami puas dengan hasilnya.
Masalah lain yang diketahui dengan Apollo Client, yang juga kami temui, adalah kemungkinan putaran kueri tak terbatas dari hook ʻuseQuery`. Inti masalahnya adalah bahwa Klien Apollo terus mengirim permintaan tanpa batas hingga berhasil menerima data. Hal ini dapat menyebabkan situasi di mana komponen "hang" dalam permintaan tanpa akhir, jika server tidak dapat mengembalikan data karena alasan tertentu.
Dalam kasus kami, salah satu alasannya adalah perubahan skema di bagian belakang. Apollo menghasilkan tipe sendiri, jadi saat menulis kueri di depan, kami harus mengikuti tipe yang dihasilkan untuk menghindari bug. Misalnya, kami memiliki permintaan yang berfungsi, tanpa masalah jenis apa pun. Namun, saat mengubah skema pada bidang belakang, jenisnya berubah pada saat yang sama, karena itu permintaan yang berfungsi dapat berhenti berfungsi. Mengingat hal ini, maka optimal untuk segera menerapkan logging dan sistem penanganan error yang jelas untuk menghemat waktu dan saraf tim.
Menurut pendapat kami, ternyata cukup berguna bahwa dalam kueri graphql Anda dapat menentukan dengan tepat data apa yang harus diterima. Saat mengirim permintaan dalam jumlah besar, ini menghindari pemrosesan data yang tidak perlu. Sebaliknya, hal ini dapat memengaruhi performa secara signifikan seiring dengan bertambahnya jumlah data.
Perlu dicatat bahwa salah satu keunggulan GraphQL adalah kenyamanan pengembangan dan dukungan API, tetapi properti ini lebih signifikan untuk pengembangan backend dan, menurut pengamatan kami, tidak memiliki dampak signifikan di bagian depan. Karena pembuatan jenis, setiap kali skema diubah pada bidang belakang, kami menulis ulang semua kueri yang terpengaruh. Beck juga harus menyempurnakan skema tersebut jika kami perlu mendapatkan sesuatu di depan yang belum dilaksanakan. Pada saat yang sama, pembuatan tipe saat menggunakan TypeScript memungkinkan untuk menangkap banyak kesalahan pada tahap penulisan kode.
Menyimpulkan
Menurut pengamatan kami, GraphQL banyak digunakan dalam berbagai jenis solusi IT dan memberikan keuntungan tertentu bagi tim pengembangan. Mari kita rangkum fitur utama GraphQL yang kami temui saat mengembangkan proyek:
- . graphql , TypeScript .
- . GraphQL - . , ( , ). graphql «» ,
- . graphql- , . .
- . GraphQL , .
! , .