ক্লায়েন্ট-সাইড রেন্ডারিং (CSR)
এই পাঠে যা শিখবেন
- CSR-এ রেন্ডারিং ঠিক কোন ধাপে, কোথায় ঘটে -- সার্ভার বনাম ক্লায়েন্টের ভূমিকা
- একটি ভাগ করা
render(template, data)হেল্পার -- এই মডিউলের বাকি পাঠগুলোতেও একই ধারণা reused হবে - Python দিয়ে CSR সিমুলেট করে
render()-এর প্রকৃত ইনভোকেশন গোনা -- কখন, কতবার কল হয় তা যাচাই করা - CSR-এর trade-off: প্রথম-লোড বিলম্ব বনাম পরবর্তী নেভিগেশনের গতি
১ · CSR-এ রেন্ডারিং কোথায় ঘটে
ক্লায়েন্ট-সাইড রেন্ডারিংClient-Side Rendering (CSR)একটি রেন্ডারিং স্ট্র্যাটেজি যেখানে সার্ভার শুধু একটি প্রায়-খালি HTML শেল ও JavaScript পাঠায়; আসল HTML ব্রাউজারে, ডেটা আনার পর তৈরি হয়।
-তে সার্ভারের কাজ ন্যূনতম -- এটি শুধু একটি হালকা HTML "শেল" (সাধারণত একটি খালি <div id="root">-এর
মতো) এবং একটি JavaScript বান্ডেলের লিংক পাঠায়। এরপর সবকিছু ব্রাউজারে ঘটে: JS বান্ডেল ডাউনলোড ও এক্সিকিউট হয়,
সেই JS একটি API কল করে প্রয়োজনীয় ডেটা আনে, এবং তারপর ব্রাউজারেই টেমপ্লেট ও ডেটা মিলিয়ে আসল HTML তৈরি হয়।
render() কলটি ঘটে ব্রাউজারে, API থেকে ডেটা পাওয়ার পরে।নিচের কোড সেলে JS bundle "এক্সিকিউট" হওয়াকে Python ফাংশন কল দিয়ে সিমুলেট করা হয়েছে -- আসল ব্রাউজারে এই কাজ করে React/Vue/Angular-এর মতো লাইব্রেরি, যাদের ভাষাগত ভিত্তি JavaScript Programming কোর্সে তৈরি হয়েছে।
২ · CSR সিমুলেশন -- render() কোথায়, কতবার কল হয়
নিচের কোড সেলে একটি ভাগ করা render(template, data) হেল্পার তৈরি করা হয়েছে -- এটি শুধু
str.format() দিয়ে টেমপ্লেটে ডেটা বসায়। এই একই ফাংশনের ধারণা L39-L42 জুড়ে reused হবে। এখানে
৩টি সিমুলেটেড পেজ-লোড চালানো হয়েছে, প্রতিটির জন্য একটি সিমুলেটেড API কল (api_fetch_dashboard_data)
ও তারপর একটি render() কল -- দুটোই ক্লায়েন্ট ধাপে, [client] ট্যাগ দিয়ে চিহ্নিত।
# ---------- ভাগ করা render() হেল্পার -- এই মডিউল জুড়ে reused হবে ----------
render_call_log = [] # প্রতিটি render() কল ঠিক কোন ধাপে হলো তার লগ
def render(template, data):
"""ছোট্ট, real টেমপ্লেট-রেন্ডার ফাংশন -- str.format() ভিত্তিক।"""
return template.format(**data)
# ---------- সিমুলেটেড API কল -- ব্যাক-এন্ড থেকে raw ডেটা আনার স্ট্যান্ড-ইন ----------
def api_fetch_dashboard_data(user_id):
fake_backend_db = {
1: {"username": "Rakib", "unread_count": 3},
2: {"username": "Priya", "unread_count": 0},
3: {"username": "Sadia", "unread_count": 7},
}
return fake_backend_db[user_id]
template = "<h1>স্বাগতম, {username}</h1><p>অপঠিত নোটিফিকেশন: {unread_count}</p>"
def simulate_csr_page_load(load_number, user_id):
print(f"--- পেজ লোড #{load_number} ---")
print("[server] খালি HTML শেল + JS bundle পাঠানো হলো -- render() এখনো ডাকা হয়নি")
print(f"[client] JS bundle এক্সিকিউট শুরু -- API কল হচ্ছে (user_id={user_id})")
data = api_fetch_dashboard_data(user_id)
print(f"[client] API রেসপন্স এসেছে: {data}")
html = render(template, data)
render_call_log.append(f"পেজ লোড #{load_number} -- client-এ")
print(f"[client] render() কল হলো -- HTML: {html}")
return html
for i, uid in enumerate([1, 2, 3], start=1):
simulate_csr_page_load(i, uid)
print()
print("render() কল লগ:")
for entry in render_call_log:
print(f" - {entry}")
print(f"\nমোট render() ইনভোকেশন: {len(render_call_log)}")
print(f"মোট পেজ লোড: 3")
print(f"প্রতি পেজ লোডে render() ঠিক একবার কল হয়েছে কি না: {len(render_call_log) == 3}")
render() কখনোই [server] ধাপে কল হয়নি -- প্রতিটি কল
simulate_csr_page_load-এর ভেতর, api_fetch_dashboard_data থেকে ডেটা পাওয়ার
পরে, [client] ধাপে ঘটেছে। ৩টি পেজ লোডের জন্য render_call_log-এ
ঠিক ৩টি এন্ট্রি জমা হয়েছে -- অর্থাৎ পেজ-লোড সংখ্যা ও render() ইনভোকেশন সংখ্যা সবসময় সমান থাকবে,
কারণ প্রতিটি লোডে ব্রাউজার নিজে ঠিক একবার রেন্ডার করে।
৩ · CSR-এর trade-off
CSR-এর সুবিধা হলো সার্ভারের কাজ ন্যূনতম -- এটি শুধু স্ট্যাটিক ফাইল সার্ভ করে, তাই সহজে স্কেল করা যায়। কিন্তু
ব্যবহারকারী প্রথমবার পেজ খুললে তাকে অপেক্ষা করতে হয় JS bundle ডাউনলোড, এক্সিকিউশন, ও API রাউন্ড-ট্রিপ শেষ
হওয়া পর্যন্ত -- এই সময়টুকু ব্যবহারকারী একটি খালি বা লোডিং-স্পিনার-সহ পেজ দেখে। L39-এ আমরা দেখব SSR কীভাবে এই
সমস্যাটি সমাধান করে render()-কে সার্ভারে সরিয়ে নিয়ে।
CSR-এ render() কল হয় শুধু ক্লায়েন্টে (ব্রাউজারে), প্রতি পেজ-লোডে ঠিক একবার -- সার্ভার শুধু একটি
শেল ও JS পাঠায়, কোনো HTML সে নিজে তৈরি করে না। পরবর্তী পাঠে (L39, SSR) একই render() ধারণা
সার্ভারে সরে যাবে -- অবস্থান পাল্টাবে, কিন্তু "প্রতি ঘটনায় ঠিক একবার" নিয়মটি একই থাকবে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন -- তারপর "→ উত্তর" চাপুন।
প্র ০১
উপরের কোডে render() কখনো [server] প্রিন্ট-লাইনের ভেতর কল হয়নি কেন?
কারণ CSR স্ট্র্যাটেজিতে সার্ভারের দায়িত্ব শুধু একটি স্ট্যাটিক শেল ও JS bundle পাঠানো -- এটি কোনো ডেটা
জানে না বা কোনো টেমপ্লেট রেন্ডার করে না। render() ফাংশনটি সংজ্ঞায়িত করা হয়েছে ঠিকই, কিন্তু
এটি প্রথম কল হয় simulate_csr_page_load-এর ভেতরে, যেখানে সেটি [client]-ট্যাগযুক্ত
লাইনগুলোর মধ্যে ঘটে -- ডেটা API থেকে পাওয়ার পরে।
প্র ০২
যদি আরও ৭টি পেজ লোড যোগ করা হয় (মোট ১০টি), render_call_log-এর দৈর্ঘ্য কত হবে?
১০ হবে। প্রতিটি সিমুলেটেড পেজ লোডে simulate_csr_page_load ফাংশনটি ঠিক একবার
render() কল করে ও render_call_log-এ একটি এন্ট্রি যোগ করে -- তাই পেজ-লোড সংখ্যা
ও render() ইনভোকেশন সংখ্যা সবসময় সমান থাকবে, CSR-এ এই সম্পর্কটি সবসময় ১:১।
প্র ০৩ CSR-এ ব্যবহারকারী কেন প্রথমবার পেজ খোলার সময় একটি "খালি" বা লোডিং অবস্থা দেখতে পারে?
কারণ সার্ভার শুরুতে যা পাঠায় তা প্রায়-খালি একটি HTML শেল -- আসল কন্টেন্ট তৈরি হওয়ার আগে তিনটি ধাপ শেষ হতে হয়: JS bundle ডাউনলোড, তা এক্সিকিউট হওয়া, এবং API কল থেকে ডেটা ফিরে আসা। এই পুরো সময়টুকু ব্রাউজারের স্ক্রিনে দেখানোর মতো প্রকৃত HTML এখনো তৈরিই হয়নি।
অনুশীলন
-
চিন্তা করুন: CSR-এ যদি একটি ব্যবহারকারীর ইন্টারনেট ধীরগতির হয় (JS bundle ডাউনলোড হতে
বেশি সময় লাগে), তাহলে এর প্রভাব ঠিক কোন ধাপে সবচেয়ে বেশি পড়বে -- সার্ভারের কাজে, নাকি ক্লায়েন্টের কাজে?
ক্লায়েন্টের কাজে। সার্ভারের কাজ (শেল ও JS পাঠানো) ধীরগতির ইন্টারনেটেও একই থাকে -- সমস্যা হয় সেই পাঠানো ফাইলগুলো ব্রাউজার পর্যন্ত পৌঁছাতে ও এক্সিকিউট হতে বেশি সময় লাগায়, কারণ
render()কল হওয়ার আগে পুরো JS bundle ডাউনলোড ও এক্সিকিউট শেষ হতে হয় -- এটাই CSR-এর একটি মূল দুর্বলতা। -
পরীক্ষা করুন: উপরের কোড সেলে
fake_backend_db-এ একটি নতুন ইউজার4: {"username": "Tamim", "unread_count": 12}যোগ করুন, তারপরfor i, uid in enumerate([1, 2, 3, 4], start=1)-এ পরিবর্তন করে দেখুনrender_call_log-এর দৈর্ঘ্য ৪ হয়েছে কি না।হ্যাঁ, নতুন ইউজার যোগ করার পর ৪টি পেজ-লোড সিমুলেট হবে, প্রতিটি নিজের API কল ও নিজের
render()কল করবে -- তাইlen(render_call_log)এখন ৪ দেখাবে, নিশ্চিত করবে পেজ-লোড সংখ্যা ওrender()ইনভোকেশন সংখ্যা এখনো সমান।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পরবর্তী পাঠ L39 সার্ভার-সাইড রেন্ডারিং (SSR) -- একই render() হেল্পার এবার সার্ভারে, প্রতি রিকোয়েস্টে কল হয় দেখুন।
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৮টি পাঠ আর্কিটেকচার প্যাটার্ন, ফ্রন্ট-এন্ড/ব্যাক-এন্ড ফ্রেমওয়ার্ক ফান্ডামেন্টাল, স্টেট ম্যানেজমেন্ট, REST API, ORM, অথেন্টিকেশন, রেন্ডারিং স্ট্র্যাটেজি ও ডিপ্লয়মেন্ট।
- JavaScript Programming কোর্স সহোদর কোর্স CSR-এ ব্রাউজারে যা ঘটে (JS bundle এক্সিকিউশন, DOM আপডেট) তার ভাষাগত ভিত্তি সেই কোর্সে তৈরি হয়েছে।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Programming Languages & Compiler Design, Software Engineering & Git, Theory of Computation, Engineering Economics ও Full-Stack Web Frameworks -- সব এক জায়গায়।