در یک برنامه بر پایه REST API، سرور شکل و اندازه منبع فراهم شده توسط endpoint را تعیین میکند. پس هر درخواست ارسال شده به سرور، مقداری داده را بارگذاری میکند، که گاهی اوقات از میزان مد نظر بیشتر است.
GraphQL ما را قادر میسازد تا تعریف کنیم که دقیقا چه دادههایی را از سرور میخواهیم؛ آزادی درخواست دادههای، چه به مقدار زیاد و چه به مقدار کم را به ما میدهد و این مشکل را حل میکند. در این پست، یاد میگیرید که چگونه میتوانید سرور GraphQL خود را با استفاده از Node و MongoDB راهاندازی کنید. همچنین نحوه ساخت mutationهایی برای بروزرسانی و حذف دادهها، کوئریهایی برای بارگذاری دادههایی خاص، و نحوه اتصال GraphQL و MongoDB با استفاده از Mongoose را خواهید دید.
شروع کار
شاخه جدیدی در سیستم خود بسازید:
$ mkdir hero-gql
$ cd hero-gql
داخل این شاخه، برخی Dependencyهای توسعهدهنده را نصب کنید:
$ yarn add babel-cli babel-preset-env babel-preset-es2015 babel-preset-stage-2 babel-register nodemon -D
در اینجا، از babel برای Transpile کردن کد ES6 به ES5 استفاده شده است.
حال یک فایل پیکربندی babel به نام .babelrc در شاخه مورد نظر بسازید. در داخل این فایل، کد زیر را بنویسید:
{"presets": ["env", "stage-2"]}
در داخل فایل package.json، بخشهای scripts و main را به این صورت بنویسید:
{
"main": "src/app.js",
"scripts": {
"start": "nodemon src/app.js --exec babel-node --presets env,stage-2",
"build": "babel src -d dist --source-maps",
"serve": "node dist/app.js"
},
// leave everything else as it is
}
ساخت یک سرور Express در Node
Express یک فریموورک منعطف Node است که امکانات قدرتمندی برای توسعه وباپلیکیشن ما فراهم میکند.
برای ساخت یک سرور Express برای برنامه خود، در ابتدا Express را به عنوان یک Dependency بر روی سیستم خود نصب کنید.
پوشهای به نام src به همراه فایلی به نام app.js داخل آن بسازید و این کد را در آن قرار دهید:
import express from 'express';
const app = express();
const PORT = 3000;
app.get('/', (request, response) => {
return response.json({
msg: 'Hello World'
})
})
app.listen(PORT, () => {
console.log(`Server is running at PORT ${PORT}`);
});
اسکریپت start را با استفاده از NPM / Yarn بر روی ترمینال خود اجرا کنید و کار آن را ببینید.
سرور GraphQL HTTP
برای ساخت یک سرور GraphQL HTTP، در ابتدا باید express-graphql، graphql و graphql-tools را به عنوان Dependency در پروژه خود نصب کنیم.
$ yarn add express-graphql graphql-tools graphql
در فایل app.js، ابتدا graphqlHTTP را از پکیج express-graphql وارد کنید.
import graphqlHTTP from 'express-graphql';
از تابع graphqlHTTP به این صورت داخل فایل استفاده کنید:
const schema = {};
app.use('/graphql', graphqlHTTP({
graphiql: true,
schema
}));
برای اجرای اسکریپت start با استفاده از NPM / Yarn، به آدرس localhost:3000/graphql در مرورگر خود بروید.
چیزی که در مرورگر خود به دست میآورید، GraphiQL نام دارد. این ابزار جدیدی ساخته شده توسط Facebook، برای آزمایش endpointهای GraphQL، queryها و mutationها است.
نگران error در GraphiQL نباشید. تنها علت دریافت آن، این است که هنوز یک ابجکت طرح معتبر تعریف نکردهایم.
ساخت یک آبجکت طرح معتبر
Schema، یک مدل از دادههایی است که میتوانند توسط سرور GraphQL دریافت شوند. Schema کوئریهایی که یک کلاینت میتواند در GraphQL اجرا کند، نوع دادههایی که میتوانند از سرور دریافت شوند و ارتباطی که میتواند میان انواع مختلف دادهها وجود داشته باشد را تعریف میکند.
در حال حاضر ما در برنامه خود، schema را به عنوان یک آبجکت خالی تعریف کردهایم، که کار معتبری نیست.
در داخل پوشه src، دو فایل ایجاد کنید:
- schema.js
- resolvers.js
داخل فایل schema.js، این کد را قرار دهید:
import {makeExecutableSchema} from 'graphql-tools';
import {resolvers} from './resolvers';
const typeDefs = `
type Query {
name: String!
}
`
export default makeExecutableSchema({
typeDefs,
resolvers
});
من در اینجا، makeExecutableSchema را از پکیج graphql-tools وارد میکنم. ما باید از این متد برای ساخت طرح GraphQL استفاده کنیم. همچنین در همینجا، resolvers که داخل فایل resolvers.js ساخته خواهد شد را وارد میکنیم.
حال بیایید typeDefs را نیز تعریف کنیم. این مورد، یک type (نوع) Query را شامل خواهد شد که فیلد name را به عنوان یک نوع string تعریف میکند.
در آخر، آبجکت schema را با کمک makeExecutableSchema خروجی میگیریم. آبجکت schema، دو فایل typeDefs و resolvers را در بر خواهد گرفت.
در داخل فایل resolvers.js، به این صورت آبجکتی به نام resolvers بسازید:
export const resolvers = {
Query: {
name (root, args, context, info) {
return 'Rajat S';
},
},
};
آبجکت resolvers چهار آرگومان را دریافت میکند: root، args، context و info. فعلا، این آبجکت یک رشته ساده را بر میگرداند.
حال باید این آبجکت را با فایل app.js ادغام کنیم. در ابتدا، آبجکت schema را به این فایل وارد کنید و خط const schema = { }; را حذف کنید.
import schema from './schema';
به آدرس localhost:3000/graphql رفته، و اسکریپت start را با استفاده از NPM / Yarn مجددا اجرا کنید.
Resolver و آرگومانهایش
برای این که سرورهای GraphQLبه کوئریهای ما پاسخ دهند، schema باید تابع resolver را برای تمام فیلدها داشته باشد. Resolver نمیتواند داخل schema شامل شود؛ بلکه باید به صورت جداگانه اضافه شود.
داخل فایل schema.js، فیلد دیگری داخل typeDefs تعریف کنید:
const typeDefs = `
type Query {
name: String!
alias: String // new field
}
`
تفاوت میان String! و String این است که String برای یک فیلد خالی، مقدار null را بر میگرداند؛ اما String! همیشه یک خطا را بروز میدهد.
حال باید یک resolver برای فیلد alias بنویسیم. یک resolver، ۴ آرگومان را میگیرد:
- root که نتیجه کوئری مربوط به مقدار والد را بر میگرداند.
- args که آرگومانها را دریافت میکند.
- Context که برای به اشتراک گذاری یک آبجکت مشابه، با هر متد resolver استفاده میشود.
- info که برای دریافت اطلاعات درباره GraphQL استفاده میشود.
داخل typeDefs، به این صورت یک آرگومان را به alias منتقل کنید:
const typeDefs = `
type Query {
name: String!
alias(heroName: String!): String!
}
`
به فایل resolvers.s بروید و یک resolver برای alias بنویسید:
export const resolvers = {
Query: {
name (root, args, context, info) {
return 'Rajat S';
},
alias(root, {heroName}, context, info) {
return heroName;
}
},
};
با اجرای یک کوئری برای alias در GraphQL، خروجیای به این شکل دریافت خواهید کرد:
Context میتواند برای فراهم کردن نوعی اطلاعات احراز هویت استفاده شود. در داخل فایل app.js، یک context داخل متد app.use اضافه کنید.
app.use('/graphql', graphqlHTTP({
graphiql: true,
schema,
context: {
userId: 1
}
}));
برای این که ببینید آیا این کار میکند یا نه، context را داخل فایل resolvers.js لاگ کنید:
export const resolvers = {
Query: {
name (root, args, context, info) {
return 'Clark Kent';
},
alias (root, {heroName}, context, info) {
console.log (context);
return heroName;
},
},
};
صفحه GraphQL را refresh کنید و ببینید که {userID: 1} در ترمینال چاپ میشود.
Context موجود در console.log() را با info جایگزین کنید. این نتیجه را داخل ترمینال خواهید دید:
تمام رکوردها را از آرایه دریافت کنید
کوئریها در GraphQL، مشابه GET در REST هستند. کوئریها ما را قادر میسازند تا دادههایی که میخواهیم را از سرور درخواست کنیم. اما بر خلاف Rest، میتوانیم دقیقا چیزی که میخواهیم را درخواست کنیم.
در فایل schema.js، بخش typeDefs را به این صورت مجددا بنویسید:
const typeDefs = `
type Hero {
_id: ID
name: String!
alias: String!
}
type Query {
allHero: [Hero]
}
`;
در اینجا، type جدیدی به نام Hero ساختهایم که سه فیلد دارد:
- _id با نوع فیلد ID.
- name با نوع فیلد String!.
- alias با نوع فیلد String!.
من از نوع Hero داخل Query استفاده میکنم. از آنجایی که میخواهم کوئری من یک آرایه را برگرداند، Hero داخل یک براکت جمعبندی شده است.
در اینجا کار ما به پایان میرسد. امیدوارم این پست به شما در یادگیری نوشتن اِیپیآیهای GraphQL بر روی Node.js و با استفاده از MongoDB کمک کرده باشد.
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید