Deploy This Site
Deploy This Site
যে প্ল্যাটফর্ম থেকে এই কারিকুলাম পড়েছেন, সেটাকেই — এই একই repo-কে — সত্যিকারের Cloudflare Pages-এ deploy করে static-site build pipeline, preview deployment, আর edge delivery নিজের হাতে দেখুন।
কেন এই প্রজেক্ট
virtualization-cloud/edge-computing-cloudflare-workers লেসন V8
isolate, PoP, আর propagation-delay-র physics তত্ত্বীয়ভাবে ব্যাখ্যা
করেছে। কিন্তু তত্ত্বটা সবচেয়ে ভালো বোঝা যায় যখন নিজের হাতে একটা সাইট
সেই infrastructure-এর ভেতর দিয়ে পাঠান — আর এই প্রজেক্টের কৌশলটা হলো,
সেই সাইটটা যেন হুবহু অচেনা কিছু না হয়। এই প্ল্যাটফর্ম-টাই —
যে repo থেকে আপনি এই লাইনগুলো পড়ছেন — deploy করার বস্তু। astro build কমান্ড কী output দেয়, wrangler.toml-এর একটা লাইন কেন গুরুত্বপূর্ণ,
git push করার পরে ঠিক কী ঘটে ভেতরে ভেতরে — এসব প্রশ্নের উত্তর
এখন আর অন্য কারো blog post-এ পড়তে হবে না, নিজের terminal-এ দেখা যাবে।
গুরুত্বপূর্ণ একটা পার্থক্য শুরুতেই স্পষ্ট করা দরকার: এই সাইট নিজেই কোনো V8 isolate বা Cloudflare Worker চালায় না। এটা সম্পূর্ণ static — একগুচ্ছ pre-built HTML/CSS/JS ফাইল, যেগুলো Cloudflare-এর global edge network থেকে সরাসরি serve হয়, প্রতিটা request-এ নতুন কোনো কোড execute না করেই। এই প্রজেক্টের আসল শিক্ষা তাই edge-computing লেসনের “কম্পিউট কাছে আনা” গল্পের অর্ধেকটা — CDN-এর static-delivery অর্ধেকটা, যেটা লেসনে ইচ্ছাকৃতভাবে “borrowed vocabulary, repeated না” হিসেবে রাখা হয়েছিল। বাকি অর্ধেকটা — dynamic কোড isolate-এ চালানো — এই প্রজেক্টের “নিজেকে চ্যালেঞ্জ করুন” অংশে ঐচ্ছিক সম্প্রসারণ হিসেবে থাকছে।
ধাপে ধাপে
১. কী deploy হচ্ছে, বুঝে নিন — static build বনাম dynamic compute
astro.config.mjs খুলুন। এতে দেখবেন integrations: [mdx(), react(), sitemap()] আর build: { format: 'directory' }। এখানে React থাকা
মানেই এই সাইট server-এ React চালায় না — src/components/islands/-এর
client:visible কম্পোনেন্টগুলো (BinaryExplorer, LogicSim, CpuCycle,
KnowledgeGraph) শুধু ব্যবহারকারীর browser-এ hydrate হয়, নিজের একটা
ছোট JS bundle হিসেবে। বাকি সবকিছু — প্রতিটা lesson, glossary term,
project page — build time-এই সম্পূর্ণ HTML-এ রেন্ডার হয়ে যায়।
remarkMath/rehypeKatex দিয়ে math রেন্ডার, mermaid দিয়ে diagram
— সবই build-এর সময়ের কাজ, request-এর সময়ের না।
এটাই ঠিক সেই জিনিস Cloudflare Pages চায়: একটা directory ভর্তি
finished static file, যা কোনো server-side runtime ছাড়াই serve করা
যায়। package.json-এর build script দেখুন:
"build": "astro build && pagefind --site dist"
দুইটা ধাপ। প্রথমে astro build — পুরো সাইটকে static HTML/CSS/JS-এ
কম্পাইল করে dist/-এ রাখে। তারপর pagefind --site dist — সেই
dist/-এর ওপর দিয়ে একটা full-text search index বানায়। লক্ষ্য
করার মতো: pagefind search-ও কোনো server চালায় না — এটা একটা
CLI tool যা build-time-এ static index file তৈরি করে, আর browser-এ
client-side JS সেই index পড়ে ফলাফল দেখায়। “search” অনুভূতিটা
dynamic মনে হলেও, নিচে পুরোটাই static file over-the-wire — কোনো
isolate, কোনো Worker, কোনো origin server লাগে না। README-তেই এই
সীমাবদ্ধতা লেখা আছে: npm run dev-এ search কাজ করে না, কারণ index
শুধু build-এ তৈরি হয়।
Checkpoint: নিজের ভাষায় এক লাইনে লিখুন — এই সাইটের কোন অংশ build time-এ ঠিক হয়ে যায়, আর কোন অংশ (যদি থাকে) সত্যিই ব্যবহারকারীর request-এর সময় চলে। উত্তর মিলিয়ে নিন: প্রায় সবটাই build time, শুধু React island hydration আর pagefind-এর client-side query browser-এ চলে — কোনোটাই server-side dynamic compute না।
২. Local build চালিয়ে real output দেখুন
npm install # প্রথমবার হলে
npm run build
Build শেষ হলে dist/ খুলুন:
ls dist/
find dist -maxdepth 2 -type d | sort
প্রকৃত চালিয়ে পাওয়া output (এই repo-তে; সংখ্যা content বাড়লে বদলাবে, কিন্তু আকৃতিটা একই থাকবে):
$ ls dist/
404.html _astro _headers about curriculum favicon.svg glossary
graph index.html learn modules pagefind progress projects
robots.txt search sitemap-0.xml sitemap-index.xml
$ find dist -maxdepth 2 -type d | sort | head -8
dist
dist/_astro
dist/about
dist/curriculum
dist/glossary
dist/learn
dist/learn/virtualization-cloud
dist/pagefind
build: { format: 'directory' } আর trailingSlash: 'ignore'
সেটিংয়ের কারণে প্রতিটা route একটা আলাদা ফোল্ডারে তার নিজের
index.html পায় (যেমন dist/learn/virtualization-cloud/edge-computing- cloudflare-workers/index.html), শুধু flat .html ফাইলের বদলে — এটাই
clean URL (trailing slash ছাড়াই) কাজ করার প্রক্রিয়া। dist/_astro/-এ
hashed JS/CSS bundle (cache-busting-এর জন্য filename-এ content hash),
আর dist/pagefind/-এ ধাপ ১-এ বলা search index — pagefind-ui.js,
fragment/, index/ — সব static ফাইল, কোনো server-side অংশ নেই।
এবার wrangler.toml খুলুন:
name = "cs-foundation"
compatibility_date = "2025-01-01"
pages_build_output_dir = "dist"
pages_build_output_dir = "dist" লাইনটাই এই পুরো প্রজেক্টের কেন্দ্রীয়
সংযোগ — Cloudflare Pages ঠিক এই ফোল্ডারের ভেতরের প্রতিটা ফাইলকেই
তুলে নিয়ে global edge-এ ছড়িয়ে দেবে। আপনি যা dist/-এ দেখলেন,
হুবহু সেটাই পরে বিশ্বের যেকোনো জায়গা থেকে ব্যবহারকারী দেখবে —
মাঝখানে কোনো অতিরিক্ত build বা transform নেই।
Checkpoint: du -sh dist/ চালিয়ে মোট সাইজ নোট করুন, আর find dist -name "*.html" | wc -l দিয়ে কতগুলো static page আসলে generate
হয়েছে গুনুন — এই repo-তে এই লেখার সময় সংখ্যা দুটো ছিল 73M আর
794 HTML page। এই সংখ্যাটাই বলে দেবে ঠিক কতগুলো fully-rendered page
Cloudflare-এর শত শত location-এ ছড়িয়ে পড়তে চলেছে।
৩. Repo-কে Cloudflare Pages-এর সাথে যুক্ত করা
দুইটা পথ আছে, দুটোই একই জায়গায় গিয়ে থামে — dist/ আপলোড হওয়া।
পথ ক — Dashboard-এর Git integration (এই repo-র README-তেই লেখা):
- Cloudflare Dashboard → Workers & Pages → Create → Pages → Connect to Git
- এই repo বেছে নিন, branch হিসেবে
main(production branch) - Build settings হুবহু
wrangler.toml/package.json-এর সাথে মিলিয়ে দিন:- Framework preset: Astro
- Build command:
npm run build - Build output directory:
dist - Environment variable:
NODE_VERSION = 22
- Save and Deploy
এই তিনটা setting — build command, output directory, Node version —
ভুল দিলে build হয়তো সফল হবে কিন্তু ভুল ফাইল আপলোড হবে, বা Node-এর
পুরনো version-এ dependency ব্যর্থ হবে। লক্ষ্য করুন build output
directory ফিল্ডটা wrangler.toml-এর pages_build_output_dir-এর
dashboard-সমতুল্য — দুটো জায়গায় দুইবার একই তথ্য লেখা লাগে কারণ
dashboard-চালিত build wrangler.toml পড়ে না, wrangler CLI পড়ে।
পথ খ — wrangler CLI (স্থানীয় build, তারপর push):
npm run build
npx wrangler pages deploy dist --project-name=cs-foundation
এখানে wrangler.toml-এ ইতিমধ্যে থাকা pages_build_output_dir = "dist" আর name = "cs-foundation" wrangler নিজে পড়ে নেয়, তাই দুইটা
argument আসলে হাতে না দিলেও চলার কথা — কিন্তু স্পষ্ট করে লেখা ভালো
অভ্যাস, বিশেষত CI script-এ যেখানে config file বাইরে থেকে override
হতে পারে। প্রথমবার চালালে wrangler প্রজেক্ট না থাকলে একটা তৈরি করার
prompt দেবে।
দুই পথের পার্থক্য practical: dashboard-এর Git integration প্রতিটা push-এ নিজে থেকে build+deploy করে (পরের ধাপের বিষয়), CLI-এর পথ একটা manual, one-shot deploy — local machine বা নিজের CI script-এ build চালিয়ে শুধু upload করেন।
Checkpoint: যেকোনো একটা পথে একটা প্রথম deploy সফল করুন, আর
dashboard-এ (বা wrangler pages deployment list-এ) একটা live URL
(<project>.pages.dev) পান।
৪. এখান থেকে যে CI/CD pipeline তৈরি হয়
Dashboard-এর Git integration বেছে নিলে, এখন থেকে main-এ প্রতিটা
push একটা স্বয়ংক্রিয় চেইন ট্রিগার করে: Cloudflare একটা isolated
build container-এ npm run build চালায়, সফল হলে dist/-এর নতুন
কনটেন্ট edge-এ প্রচার করে, ব্যর্থ হলে আগের deployment অক্ষত থাকে।
মানুষের হাতে “deploy” বোতাম চাপার দরকার নেই — git push-ই deploy।
আরও একটা প্র্যাকটিক্যাল প্যাটার্ন এখানে ফ্রি পাওয়া যায় —
preview deployment। main ছাড়া অন্য কোনো branch push করলে,
বা একটা pull request খুললে, Cloudflare সেই কোডের জন্য একটা আলাদা,
অস্থায়ী URL-এ deploy করে (সাধারণত branch/commit hash-ভিত্তিক
subdomain) — production URL-কে স্পর্শ না করেই। এর মানে একটা নতুন
lesson content-এর change merge করার আগেই, একটা shareable link-এ
আসলে কেমন দেখাচ্ছে তা রিভিউ করা যায় — কোনো local setup ছাড়াই
সহকর্মী বা reviewer-কে লিংক পাঠানো যায়।
এই পুরো প্যাটার্নটাকে virtualization-cloud/infrastructure-as-code-terraform
লেসনের ভাষায় দেখলে চেনা লাগবে: git push হলো একটা declarative
ঘোষণা — “সাইটের কনটেন্ট এখন এই অবস্থায় থাকা উচিত।” Cloudflare-এর
pipeline সেই ঘোষণা পড়ে edge-এ থাকা প্রকৃত (deployed) অবস্থার সাথে
তুলনা করে, আর ঠিক ততটুকু ফাইল re-upload/invalidate করে — Terraform-এর
plan/apply যেমন .tf-এর desired state আর state file-এর observed
state মিলিয়ে diff প্রয়োগ করে। পার্থক্য শুধু domain-এ — সেখানে cloud
resource, এখানে static file — কিন্তু “declare করো, tool নিজে
reconcile করুক” যুক্তিটা অভিন্ন।
Checkpoint: একটা ছোট, নিরাপদ change (যেমন এই ফাইলের কোনো টাইপো
ঠিক করা) একটা feature branch-এ push করুন, PR খুলুন, আর preview
URL-টা কমেন্টে বা dashboard-এ খুঁজে বের করুন। তারপর main-এ merge
করে production deploy স্বয়ংক্রিয়ভাবে শুরু হতে দেখুন।
৫. Custom domain ও DNS — সংক্ষেপে
Production URL (<project>.pages.dev)-এর বদলে নিজের domain ব্যবহার
করতে চাইলে, ধারণাটা এরকম: Pages প্রজেক্টের Custom domains
সেটিংসে ডোমেইন যোগ করুন; Cloudflare একটা DNS record (সাধারণত একটা
CNAME, বা ডোমেইন ইতিমধ্যে Cloudflare-এ থাকলে একটা প্রক্সিকৃত A/AAAA
record) সেই Pages deployment-এর দিকে নির্দেশ করতে বলবে। Record যোগ
হলে Cloudflare স্বয়ংক্রিয়ভাবে একটা managed TLS certificate provision
করে, তাই আলাদা করে HTTPS সেটআপ করা লাগে না।
কাস্টম ডোমেইন যোগ করলে দুইটা জায়গা বদলাতে ভুলবেন না (README-তেই
লেখা আছে): astro.config.mjs-এর site ফিল্ড (এখন
https://cs-foundation.pages.dev) আর public/robots.txt-এর sitemap
URL — নইলে generated sitemap আর canonical URL পুরনো domain-এ থেকে
যাবে।
Checkpoint: এক বাক্যে ব্যাখ্যা করুন — custom domain যোগ করার
পরেও কেন pages_build_output_dir বা build command কিছুই বদলাতে হয়
না। (কারণ domain শুধু routing/DNS স্তরের বিষয় — build pipeline আর
deployed content অপরিবর্তিত থাকে।)
৬. Live deployment যাচাই — edge infrastructure নিজের চোখে দেখা
Deploy হয়ে গেলে browser-এ live URL খুলে normal ভাবে ঘুরে দেখুন —
homepage, একটা lesson, search (pagefind ঠিকমতো কাজ করছে কিনা,
যেহেতু npm run dev-এ এটা টেস্ট করা যায় না)।
তারপর curl -I দিয়ে raw response header দেখুন — এটাই
edge-computing লেসনের তত্ত্বকে চোখে দেখার সুযোগ:
curl -I https://<your-project>.pages.dev/
যা দেখার মতো:
cf-ray— একটা ID যার শেষে একটা datacenter code থাকে; এটাই প্রমাণ করে অনুরোধটা সত্যিই কোন Cloudflare PoP আপনাকে serve করেছে — লেসনের “শত শত geographically-distributed location” কথাটা এখন একটা concrete header-valuecache-controlএবং সম্ভবতcf-cache-status— static asset কতক্ষণ edge-এ cache থাকবে; README-তে উল্লেখ করাpublic/_headersফাইল এই long-lived caching নির্দেশ করেserver: cloudflare— নিশ্চিত করে origin নয়, edge nodeই সরাসরি উত্তর দিচ্ছে
চাইলে একটা asset-ও চেক করুন (curl -I কোনো _astro/*.js ফাইলে) —
সেখানে cache-control-এর মেয়াদ HTML page-এর চেয়ে অনেক বেশি হওয়ার
কথা, কারণ filename-এ content-hash থাকায় asset বদলালে নতুন filename-ই
তৈরি হয়, তাই পুরনো cache নিরাপদে aggressively রাখা যায়।
Checkpoint: দুইটা আলাদা curl -I output (একটা HTML page, একটা
hashed asset) পাশাপাশি রেখে cache-control মানের পার্থক্য ব্যাখ্যা
করুন, আর cf-ray-র শেষাংশ থেকে অনুমান করুন কোন অঞ্চলের PoP আপনাকে
serve করেছে।
নিজেকে চ্যালেঞ্জ করুন
- একটা ছোট Cloudflare Pages Function যোগ করুন (
functions/ফোল্ডারে একটা.jsফাইল) — যেমন একটা/api/helloroute যা request header পড়ে JSON ফেরত দেয়; এটাই edge-computing লেসনের “dynamic অংশ” — এখন সত্যিকারের একটা V8 isolate আপনার কোড চালাবে - একটা real custom domain (নিজের বা টেস্ট-এর জন্য একটা subdomain) যোগ করে HTTPS provisioning শেষ পর্যন্ত দেখুন
- দুই-তিনটা ভিন্ন geographic location থেকে (VPN, অথবা WonderNetwork-জাতীয় public latency-test tool ব্যবহার করে) live URL-এর load latency মেপে edge-CDN effect-টা সংখ্যায় প্রমাণ করুন
- Pipeline-এ একটা build-time check যোগ করুন —
npm run check(Astro-র নিজস্ব type/content check) build command-এর আগে চালিয়ে, ভাঙা content merge হওয়ার আগেই আটকান dist/-এর total size আর file count সময়ের সাথে ট্র্যাক করুন (প্রতিটা deploy-এ), আর একটা threshold-এর বেশি বাড়লে সতর্ক করার একটা ছোট script লিখুনwrangler pages deployment listআরwrangler pages deployment tailব্যবহার করে একটা live deployment-এর real-time log দেখুন — Pages Function যোগ করলে (চ্যালেঞ্জ ১) এখানেই তার output দেখা যাবে
যা এখানে শিখলেন, পরে যেখানে লাগবে
| এখানে | পরে |
|---|---|
| Static build vs. dynamic edge compute-এর পার্থক্য | যেকোনো JAMstack/SSG প্রজেক্টে সঠিক hosting-মডেল বেছে নেওয়া |
pages_build_output_dir-কে build script-এর output-এর সাথে মিলিয়ে দেখা | যেকোনো CI/CD pipeline-এ “build output কোথায় যায়” ডিবাগ করা |
| Git push → automatic build → deploy চেইন | GitHub Actions, Vercel, Netlify-জাতীয় যেকোনো Git-triggered deployment বোঝা |
| Preview deployment workflow | Production touch না করে review করার অভ্যাস, যেকোনো টিমে |
curl -I দিয়ে response header পড়া | Production incident-এ caching/CDN সমস্যা দ্রুত নির্ণয় করা |