React Server Components কোনো স্পিড বাটন না।
সব কম্পোনেন্ট সার্ভারে নিলেও ধীর query, বড় image, duplicate request আর জটিল interaction থেকে যেতে পারে।
আসল পরিবর্তনটা অন্য জায়গায়: কোন দায়িত্ব সার্ভারে থাকবে, আর কোনটা ব্রাউজারে—Server Components আমাদের সেই সিদ্ধান্ত নিতে বাধ্য করে।
আর্কিটেকচার ভালো হয় ওই বাউন্ডারির কারণে।
Server rendering আর Server Components এক জিনিস না
দুটো শব্দ প্রায়ই একসাথে মিশে যায়।
Server-side rendering প্রথম response-এর HTML তৈরি করে। একটি Client Component-ও সার্ভারে HTML তৈরি করে পরে ব্রাউজারে hydrate হতে পারে।
React Server Component আলাদা। তার component code client JavaScript bundle-এ যায় না। সে server-side data পড়তে পারে, interface সাজাতে পারে; কিন্তু browser state, effect বা event handler ব্যবহার করতে পারে না।
তাই প্রথম প্রশ্নটা খুব সোজা:
এই কম্পোনেন্টের কি browser capability দরকার, নাকি শুধু data পড়ে render করলেই হবে?
শুধু data আর render হলে আমি server থেকেই শুরু করি।
ক্লায়েন্ট প্রজেক্টে যে বাউন্ডারি ব্যবহার করি
Server side সামলায়:
- authentication ও authorization;
- database আর private API;
- secret-সহ provider SDK;
- data normalization;
- প্রথম meaningful content;
- browser-এর উপর ভরসা করা যায় না—এমন সব সিদ্ধান্ত।
Client side সামলায়:
- click, input, drag ও keyboard interaction;
- local optimistic state;
- browser-only API;
- live user input-নির্ভর animation;
- সত্যিই hydration দরকার এমন ছোট অংশ।
এটা purity contest না। Form-টা Client Component হতে পারে, অথচ তার চারপাশের page server-এ থাকতে পারে।
Database record না, safe DTO পাঠান
সবচেয়ে গুরুত্বপূর্ণ implementation detail হলো—বাউন্ডারি পেরিয়ে কোন data যাচ্ছে।
type PublicAccount = {
displayName: string;
planLabel: string;
};
async function getPublicAccount(userId: string): Promise<PublicAccount> {
const account = await db.account.findUniqueOrThrow({
where: { userId },
select: {
displayName: true,
plan: true,
},
});
return {
displayName: account.displayName,
planLabel: account.plan,
};
}
export default async function AccountPage() {
const session = await requireSession();
const account = await getPublicAccount(session.user.id);
return <AccountSwitcher initialAccount={account} />;
}
Browser শুধু দরকারি দুইটি field পায়।
Internal ID, billing record, provider token বা সুবিধার জন্য পুরো database object পাঠানো হয় না।
আমার নিয়ম: কোনো value Client Component-এ গেলে, সেই user-এর কাছে সেটাকে public ধরুন। TypeScript unsafe payload-কে private বানায় না।
Composition client boundary ছোট রাখে
একটি nested button-এর state দরকার বলে পুরো layout-এ "use client" বসানো পরিচিত ভুল। এতে imported subtree-ও client code হয়ে যায়।
Interactive leaf-টা ছোট রাখি:
export default async function ProjectPage() {
const project = await getProject();
return (
<article>
<ProjectSummary project={project} />
<ProjectActions projectId={project.id} />
</article>
);
}
ProjectSummary server-এ থাকে। শুধু ProjectActions focused Client Component।
Client-side data request-এর অপেক্ষা ছাড়াই page পড়া যায়, আবার action area-ও application-এর মতো কাজ করে।
Server Components যা সমাধান করে না
এগুলো নিজে থেকে ঠিক করে না:
- একটার পর একটা database call;
- ভুল cache বা revalidation;
- ধীর origin response;
- server-এ unbounded work;
- ভুল image sizing;
- layout shift;
- insecure mutation।
Slow request server-এ নেওয়ায় spinner হয়তো গেল, কিন্তু user-এর অপেক্ষা যায়নি।
পুরো request path মাপতে হবে।
ব্যবহারিক সিদ্ধান্ত
Server Components-কে আমি ownership tool হিসেবে ব্যবহার করি:
- server truth-এর কাছে fetch আর authorization;
- সবচেয়ে ছোট safe DTO;
- client JavaScript-এর আগে useful content;
- শুধু দরকারি interaction hydrate;
- component না, পুরো request measure।
আরও নির্দিষ্ট checklist-এর জন্য পড়ুন Next.js server-client boundary আমি কীভাবে আঁকি। Framework-এর বর্তমান behavior আছে official Next.js guide-এ।
পুরোনো React app যদি এক বিশাল client boundary হয়ে যায়, architecture problem-টা জানান। কোথা থেকে আলাদা করা উচিত—সেটা বলব।
- #React
- #Server Components
- #Next.js
- #পারফরম্যান্স
- #সিকিউরিটি

আরও পড়ুন
ইঞ্জিনিয়ারিং, SaaS, ফ্রিল্যান্সিং আর নির্ভরযোগ্য প্রোডাক্ট তৈরির সম্পর্কিত লেখা।