স্ট্যাটিক সাইট জেনারেশন (SSG)
এই পাঠে যা শিখবেন
- SSG-তে "বিল্ড টাইম" ও "রিকোয়েস্ট টাইম" আলাদা দুটি ধাপ কীভাবে কাজ করে
- Python দিয়ে SSG সিমুলেট করে
render()ইনভোকেশন (১) বনাম সার্ভ হওয়া রিকোয়েস্ট (১০০০) গোনা - কেন SSG সবচেয়ে দ্রুত serving দেয়, কিন্তু কেন এটি স্টেল কনটেন্টের ঝুঁকি বহন করে
- SSR (L39) ও SSG-এর মধ্যে
render()-এর ফ্রিকোয়েন্সির সরাসরি তুলনা
১ · SSG-তে দুটি আলাদা ধাপ -- বিল্ড টাইম ও রিকোয়েস্ট টাইম
স্ট্যাটিক সাইট জেনারেশনStatic Site Generation (SSG)একটি রেন্ডারিং স্ট্র্যাটেজি যেখানে HTML একবার, বিল্ড টাইমে তৈরি ও ক্যাশ করা হয়, তারপর সেই একই ফলাফল বারবার সার্ভ করা হয়।
-তে render() ওয়েবসাইট ডিপ্লয় করার আগে, একটি "বিল্ড" ধাপে একবারই কল হয়। এই বিল্ড
ধাপে CMS বা ফাইল থেকে ডেটা আনা হয়, টেমপ্লেটের সাথে মিলিয়ে চূড়ান্ত HTML তৈরি হয়, ও সেই HTML একটি ক্যাশে
(এখানে সিমুলেশনে, শুধু একটি ভ্যারিয়েবলে) সংরক্ষিত হয়। এরপর যতগুলো রিকোয়েস্টই আসুক না কেন, প্রতিটি সেই একই
সংরক্ষিত HTML স্ট্রিং পায় -- কোনো নতুন ডেটা-আনা বা রেন্ডার-কাজ ছাড়াই।
ডিপ্লয়ের আগে একবার ঘটে -- ডেটা আনা হয়,
render() কল হয়, ফলাফল ক্যাশে সংরক্ষিত হয়।প্রতিটি রিকোয়েস্টে ঘটে -- ক্যাশ থেকে সরাসরি একই HTML সার্ভ হয়,
render() কল হয় না।২ · SSG সিমুলেশন -- ১ বার render(), ১০০০ রিকোয়েস্ট সার্ভ
নিচের কোড সেলে একই render(template, data) হেল্পার ব্যবহৃত হয়েছে। প্রথমে "বিল্ড টাইম" ধাপে
render() ঠিক একবার কল হয়ে ফলাফল CACHED_HTML-এ সংরক্ষিত হয়। তারপর
handle_request_from_cache ফাংশনটি ১০০০ বার কল করে দেখা হয়েছে -- খেয়াল করুন এই ফাংশনের ভেতর
render()-এর কোনো কল-ই নেই, শুধু সংরক্ষিত ভ্যারিয়েবল রিটার্ন হচ্ছে।
render_call_log = []
def render(template, data):
"""L38-L39-এর একই ধারণা -- str.format() ভিত্তিক টেমপ্লেট-রেন্ডার।"""
return template.format(**data)
def load_content_from_cms():
# বিল্ড-টাইমে একবার CMS/মার্কডাউন ফাইল থেকে আসা কনটেন্ট -- ব্যয়বহুল কাজ
return {
"title": "রেন্ডারিং স্ট্র্যাটেজি বোঝা",
"author": "ABCL TECH টিম",
"body": "এই পোস্টে আমরা CSR, SSR ও SSG নিয়ে আলোচনা করেছি।",
}
template = "<article><h1>{title}</h1><p class='byline'>লিখেছেন: {author}</p><p>{body}</p></article>"
# ---------- ধাপ ১: বিল্ড টাইম -- render() ঠিক একবার কল হয় ----------
print("=== বিল্ড টাইম শুরু ===")
build_data = load_content_from_cms()
CACHED_HTML = render(template, build_data)
render_call_log.append("বিল্ড টাইম (একবার)")
print("[build] render() কল হলো -- ফলাফল ক্যাশে সংরক্ষিত হলো")
print(f"[build] ক্যাশড HTML: {CACHED_HTML}")
print("=== বিল্ড টাইম শেষ, সাইট এখন ডিপ্লয় করার জন্য প্রস্তুত ===\n")
# ---------- ধাপ ২: রিকোয়েস্ট টাইম -- render() আর কল হয় না, শুধু ক্যাশ সার্ভ হয় ----------
def handle_request_from_cache(request_number):
# লক্ষ্য করুন: এখানে render() কোথাও কল করা হয়নি -- সরাসরি ক্যাশড স্ট্রিং রিটার্ন
return CACHED_HTML
TOTAL_SIMULATED_REQUESTS = 1000
served_count = 0
for i in range(1, TOTAL_SIMULATED_REQUESTS + 1):
html = handle_request_from_cache(i)
served_count += 1
print(f"সিমুলেটেড রিকোয়েস্ট সার্ভ হলো: {served_count}")
print(f"render() মোট ইনভোকেশন: {len(render_call_log)}")
print(f"render_call_log বিস্তারিত: {render_call_log}")
print(f"\nরেন্ডার-বনাম-সার্ভ অনুপাত: {len(render_call_log)} render() কল : {served_count} রিকোয়েস্ট সার্ভ")
render_call_log-এর দৈর্ঘ্য পুরো কোড চলার পরেও ১ -- handle_request_from_cache
ফাংশনটি ১০০০ বার কল হলেও, প্রতিবারই এটি শুধু CACHED_HTML ভ্যারিয়েবল রিটার্ন করে, যা বিল্ড টাইমে
একবারই তৈরি হয়েছিল। এই এক লাইনের পার্থক্য (render() কল করা বনাম আগে থেকে সংরক্ষিত মান রিটার্ন করা)-ই
SSR ও SSG-এর মধ্যে মৌলিক পার্থক্য তৈরি করে।
৩ · গতি বনাম স্টেলনেস -- SSG-এর মূল trade-off
SSG-এর সার্ভিং ধাপ অত্যন্ত দ্রুত ও সস্তা -- সার্ভারকে প্রতি রিকোয়েস্টে কোনো ডেটাবেস কল, API কল, বা টেমপ্লেট-রেন্ডার
কাজ করতে হয় না, শুধু একটি প্রি-বিল্ট ফাইল/স্ট্রিং সার্ভ করতে হয় (বাস্তবে প্রায়ই একটি CDN থেকে)। কিন্তু এর মূল্য
হলো: load_content_from_cms()-এর আসল ডেটা যদি বিল্ডের পরে বদলে যায় (যেমন উপরের উদাহরণে
body টেক্সট আপডেট হয়), CACHED_HTML তা প্রতিফলিত করবে না -- যতক্ষণ না একটি নতুন
বিল্ড চালিয়ে render() আবার কল করা হয়। এই "স্টেল কনটেন্ট" সমস্যাটিই L41-এ ISR সমাধান করবে -- একটি
নিয়ন্ত্রিত সময়-ব্যবধানে স্বয়ংক্রিয়ভাবে পুনরায় রেন্ডার করে।
SSG-তে render() ঠিক একবার, বিল্ড টাইমে কল হয় -- ফলাফল ক্যাশে সংরক্ষিত হয়ে থাকে, ও প্রতিটি
পরবর্তী রিকোয়েস্ট সেই একই ক্যাশড HTML পায়, আবার রেন্ডার না করেই। SSR (L39)-এর সাথে তুলনায়: SSR প্রতি
রিকোয়েস্টে সঠিক ও আপ-টু-ডেট কিন্তু ধীর ও ব্যয়বহুল; SSG অত্যন্ত দ্রুত কিন্তু পরের বিল্ড পর্যন্ত ডেটা স্টেল থেকে
যেতে পারে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন -- তারপর "→ উত্তর" চাপুন।
প্র ০১
handle_request_from_cache ফাংশনটি ১০০০ বার কল হলেও কেন render_call_log-এর
দৈর্ঘ্য শুধু ১?
কারণ handle_request_from_cache-এর ভেতরে render()-এর কোনো কল-ই নেই -- এটি শুধু
বিল্ড টাইমে আগে থেকে গণনা করে রাখা CACHED_HTML ভ্যারিয়েবল রিটার্ন করে। render()
শুধু render_call_log-এ এন্ট্রি যোগ করে যখন তা সত্যিই কল হয়, আর তা ঘটেছিল কেবল বিল্ড টাইমের
একটি লাইনে।
প্র ০২
যদি বিল্ড টাইমের পরে load_content_from_cms()-এর body টেক্সট পাল্টে দেওয়া
হয়, ১০০১তম রিকোয়েস্টে তা কি দেখা যাবে?
না -- কারণ CACHED_HTML বিল্ড টাইমেই একবার গণনা হয়ে গেছে এবং একটি সাধারণ ভ্যারিয়েবলে
সংরক্ষিত আছে। load_content_from_cms()-এর রিটার্ন ভ্যালু পাল্টালেও, সেই পরিবর্তন
CACHED_HTML-এ প্রতিফলিত হবে না যতক্ষণ না render() আবার কল করে নতুন করে
CACHED_HTML আপডেট করা হয় -- অর্থাৎ একটি নতুন বিল্ড না চালানো পর্যন্ত।
প্র ০৩ SSG কোন ধরনের সাইটের জন্য সবচেয়ে বেশি উপযুক্ত মনে হয় -- এবং কোন ধরনের জন্য অনুপযুক্ত?
SSG সবচেয়ে বেশি উপযুক্ত এমন কনটেন্টের জন্য যা কমই পাল্টায় ও সব ভিজিটরের জন্য একই (যেমন ডকুমেন্টেশন, ব্লগ পোস্ট, মার্কেটিং পেজ) -- কারণ একবার বিল্ড করলেই দীর্ঘদিন সঠিক থাকে। এটি অনুপযুক্ত এমন পেজের জন্য যার কনটেন্ট প্রতি-ব্যবহারকারী আলাদা বা সেকেন্ডে সেকেন্ডে পাল্টায় (যেমন একটি লাইভ স্টক-প্রাইস ড্যাশবোর্ড) -- সেখানে স্টেল ক্যাশড HTML সরাসরি ভুল তথ্য দেখাতে পারে।
অনুশীলন
-
চিন্তা করুন: SSR (L39)-এ ১০০০ রিকোয়েস্টে
render()১০০০ বার কল হতো। SSG-তে একই ১০০০ রিকোয়েস্টে মাত্র ১ বার। এই ৯৯৯ কম কলের বিনিময়ে ঠিক কী "হারানো" হয়?হারানো হয় "প্রতি রিকোয়েস্টে ডেটা তাজা থাকার" নিশ্চয়তা। SSR প্রতিটি রিকোয়েস্টে নতুন করে ডেটা আনে, তাই সবসময় সর্বশেষ অবস্থা প্রতিফলিত করে। SSG একবারই ডেটা "স্ন্যাপশট" নেয় -- এরপর সেই স্ন্যাপশটই বারবার সার্ভ হতে থাকে, আসল ডেটা যতই বদলাক না কেন, যতক্ষণ না নতুন বিল্ড হয়।
-
পরীক্ষা করুন: উপরের কোড সেলে
TOTAL_SIMULATED_REQUESTS = 1000-কেTOTAL_SIMULATED_REQUESTS = 5000-এ পরিবর্তন করে Run চাপুন, এবং দেখুনrender_call_log-এর দৈর্ঘ্য তাতে বদলায় কি না।না,
render_call_log-এর দৈর্ঘ্য এখনো ১-ই থাকবে -- কারণ রিকোয়েস্ট সংখ্যা যতই বাড়ানো হোক না কেন,render()শুধুই বিল্ড টাইমের সেই একটি লাইনে কল হয়। কেবলserved_countমান ৫০০০ হবে -- এটাই SSG-এর মূল সুবিধা প্রমাণ করে: serving-এর খরচ রিকোয়েস্ট সংখ্যা বাড়লেও render() ইনভোকেশন সংখ্যায় প্রভাব ফেলে না।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পরবর্তী পাঠ L41 ইনক্রিমেন্টাল স্ট্যাটিক রিজেনারেশন (ISR) -- SSG-এর ক্যাশে একটি স্মার্ট স্টেলনেস-চেক যোগ করে দেখুন।
- আগের পাঠ আবার দেখুন L39 SSR-এ প্রতি রিকোয়েস্টে render() কীভাবে কল হয় তা আবার দেখে এই পাঠের সাথে তুলনা করুন।
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৮টি পাঠ আর্কিটেকচার প্যাটার্ন, ফ্রন্ট-এন্ড/ব্যাক-এন্ড ফ্রেমওয়ার্ক ফান্ডামেন্টাল, স্টেট ম্যানেজমেন্ট, REST API, ORM, অথেন্টিকেশন, রেন্ডারিং স্ট্র্যাটেজি ও ডিপ্লয়মেন্ট।
- সব 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 -- সব এক জায়গায়।