🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

কিভাবে 2026 সালে Node.js এবং Apollo Server সহ একটি GraphQL API তৈরি করবেন

⏱️2 min read  ·  427 words

গ্রাফকিউএল ক্লায়েন্টদের একটি একক অনুরোধে তাদের প্রয়োজনীয় ডেটার জন্য অনুরোধ করতে দেয় — কোনো ওভার-ফেচিং নয়, কোনো আন্ডার-ফেচিং নয়। সাথে মিলিতঅ্যাপোলো সার্ভার এবং টাইপস্ক্রিপ্ট, এটি নমনীয় API তৈরি করার একটি শক্তিশালী উপায়। এই গাইড স্ক্র্যাচ থেকে একটি সম্পূর্ণ GraphQL API তৈরি করে।

GraphQL বনাম REST — দ্রুত তুলনা

দৃষ্টিভঙ্গি বিশ্রাম গ্রাফকিউএল
ডেটা আনা হচ্ছে একাধিক শেষবিন্দু একক শেষ বিন্দু, সুনির্দিষ্ট প্রশ্ন
ওভার-ফেচিং সাধারণ নির্মূল
সংস্করণ URL সংস্করণ (v1, v2) স্কিমা বিবর্তন
জন্য সেরা সহজ CRUD, ক্যাশিং জটিল, নেস্টেড, ক্লায়েন্ট-চালিত ডেটা

প্রকল্প সেটআপ

mkdir graphql-api && cd graphql-api
npm init -y
npm install @apollo/server graphql
npm install -D typescript tsx @types/node
npx tsc --init

স্কিমা সংজ্ঞায়িত করুন

// src/schema.ts
export const typeDefs = `#graphql
  type User {
    id: ID!
    name: String!
    email: String!
    posts: [Post!]!
  }

  type Post {
    id: ID!
    title: String!
    content: String!
    author: User!
    published: Boolean!
  }

  type Query {
    users: [User!]!
    user(id: ID!): User
    posts: [Post!]!
  }

  type Mutation {
    createUser(name: String!, email: String!): User!
    createPost(title: String!, content: String!, authorId: ID!): Post!
    publishPost(id: ID!): Post!
  }
`;

সমাধানকারী লিখুন

// src/resolvers.ts
import { db } from './db';

export const resolvers = {
  Query: {
    users: () => db.users.findAll(),
    user: (_: any, { id }: { id: string }) => db.users.findById(id),
    posts: () => db.posts.findAll(),
  },

  Mutation: {
    createUser: (_: any, { name, email }: { name: string; email: string }) => {
      return db.users.create({ name, email });
    },
    createPost: (_: any, args: { title: string; content: string; authorId: string }) => {
      return db.posts.create({ ...args, published: false });
    },
    publishPost: (_: any, { id }: { id: string }) => {
      return db.posts.update(id, { published: true });
    },
  },

  // Field resolvers for relationships
  User: {
    posts: (parent: { id: string }) => db.posts.findByAuthor(parent.id),
  },
  Post: {
    author: (parent: { authorId: string }) => db.users.findById(parent.authorId),
  },
};

সার্ভার তৈরি করুন

// src/index.ts
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import { typeDefs } from './schema';
import { resolvers } from './resolvers';

const server = new ApolloServer({ typeDefs, resolvers });

const { url } = await startStandaloneServer(server, {
  listen: { port: 4000 },
  context: async ({ req }) => {
    // Extract auth token, attach user to context
    const token = req.headers.authorization?.replace('Bearer ', '');
    const user = token ? await verifyToken(token) : null;
    return { user };
  },
});

console.log("GraphQL ready at " + url);

সমাধানকারীদের মধ্যে প্রমাণীকরণ

Mutation: {
  createPost: (_: any, args, context) => {
    // Require authentication
    if (!context.user) {
      throw new GraphQLError('Not authenticated', {
        extensions: { code: 'UNAUTHENTICATED' },
      });
    }
    return db.posts.create({ ...args, authorId: context.user.id });
  },
},

ডেটালোডার দিয়ে N+1 সমস্যা সমাধান করা হচ্ছে

ক্ষেত্র সমাধানকারীরা N+1 প্রশ্নগুলি ট্রিগার করতে পারে (পিতাপিতার প্রতি একটি প্রশ্ন)। DataLoader ব্যাচ এবং তাদের ক্যাশে:

npm install dataloader
import DataLoader from 'dataloader';

// Create a loader that batches user lookups
const userLoader = new DataLoader(async (ids: readonly string[]) => {
  const users = await db.users.findByIds(ids);
  // Return in the same order as requested ids
  return ids.map(id => users.find(u => u.id === id));
});

// Use in resolver — batches all author lookups into one query
Post: {
  author: (parent, _, context) => context.userLoader.load(parent.authorId),
},

উদাহরণ প্রশ্ন

# Client requests exactly what it needs
query {
  user(id: "1") {
    name
    posts {
      title
      published
    }
  }
}

# Response contains only requested fields:
# { "data": { "user": { "name": "Alice", "posts": [...] } } }

প্রায়শই জিজ্ঞাসিত প্রশ্ন

প্রশ্ন: আমার প্রকল্পের জন্য GraphQL বা REST?
উত্তর: জটিল, নেস্টেড, ক্লায়েন্ট-চালিত ডেটার জন্য গ্রাফকিউএল (মোবাইল অ্যাপস, বিভিন্ন প্রয়োজনের ড্যাশবোর্ড)। সাধারণ CRUD এর জন্য REST এবং যখন HTTP ক্যাশিং সবচেয়ে গুরুত্বপূর্ণ। অনেক দল উভয়ই ব্যবহার করে।

প্রশ্ন: গ্রাফকিউএল-এ আমি কীভাবে ফাইল আপলোডগুলি পরিচালনা করব?
উত্তর: graphql-আপলোড প্যাকেজটি ব্যবহার করুন, অথবা আরও ভাল, একটি পৃথক REST এন্ডপয়েন্ট বা নির্ধারিত URL এর মাধ্যমে অবজেক্ট স্টোরেজ (S3) এ ফাইল আপলোড করুন এবং আপনার GraphQL মিউটেশনে URL পাস করুন৷

প্রশ্ন: GraphQL কি REST এর চেয়ে ক্যাশে করা কঠিন?
উত্তর: হ্যাঁ HTTP স্তরে (একক এন্ডপয়েন্ট, POST অনুরোধ)। ক্লায়েন্টে অ্যাপোলো ক্লায়েন্টের স্বাভাবিক ক্যাশে ব্যবহার করুন এবং ক্ষতিপূরণের জন্য সার্ভারে অব্যাহত প্রশ্ন বা প্রতিক্রিয়া ক্যাশিং ব্যবহার করুন।

প্রশ্ন: আমি কীভাবে ব্যয়বহুল/দূষিত প্রশ্নগুলি প্রতিরোধ করব?
উত্তর: ক্যোয়ারী গভীরতা সীমিত, জটিলতা বিশ্লেষণ, এবং হার সীমিত যোগ করুন। graphql-depth-limit এবং graphql-query-complexity-এর মতো প্যাকেজগুলি গভীরভাবে নেস্ট করা আপত্তিজনক প্রশ্ন থেকে রক্ষা করে৷

প্রশ্ন: আমার কি কোড-প্রথম বা স্কিমা-প্রথম ব্যবহার করা উচিত?
উত্তর: স্কিমা-ফার্স্ট (এসডিএল স্ট্রিং, এখানে দেখানো হয়েছে) স্পষ্ট এবং ভাষা-অজ্ঞেয়বাদী। কোড-প্রথম (নেক্সাস, টাইপগ্রাফকিউএল) আরও ভাল টাইপস্ক্রিপ্ট ইন্টিগ্রেশন দেয়। উভয় কাজ; দলের পছন্দের উপর ভিত্তি করে বাছাই করুন।

উপসংহার

অ্যাপোলো সার্ভারের সাথে গ্রাফকিউএল ক্লায়েন্টদের তাদের আনয়ন করা ডেটার উপর সুনির্দিষ্ট নিয়ন্ত্রণ দেয়, অতিরিক্ত এবং আন্ডার-ফেচিং দূর করে। এখানে সেটআপ — টাইপ করা স্কিমা, সম্পর্কগুলির সাথে সমাধানকারী, প্রসঙ্গ-ভিত্তিক প্রমাণীকরণ এবং N+1 সমস্যার জন্য ডেটালোডার — একটি প্রোডাকশন GraphQL API-এর প্রয়োজনীয়তাগুলিকে কভার করে৷ লাইভে যাওয়ার আগে গভীরতা সীমাবদ্ধতা এবং জটিলতা বিশ্লেষণ যোগ করুন এবং ফ্রন্টএন্ডে একটি স্বাভাবিক ক্যাশের জন্য অ্যাপোলো ক্লায়েন্টের সাথে যুক্ত করুন।

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা