Foundationপ্রথম নীতি থেকে
LEVEL 12মাঝারি~৬ ঘণ্টাBash

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-তেই লেখা):

  1. Cloudflare Dashboard → Workers & Pages → Create → Pages → Connect to Git
  2. এই repo বেছে নিন, branch হিসেবে main (production branch)
  3. Build settings হুবহু wrangler.toml/package.json-এর সাথে মিলিয়ে দিন:
    • Framework preset: Astro
    • Build command: npm run build
    • Build output directory: dist
    • Environment variable: NODE_VERSION = 22
  4. 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-value
  • cache-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 করেছে।

নিজেকে চ্যালেঞ্জ করুন

  1. একটা ছোট Cloudflare Pages Function যোগ করুন (functions/ ফোল্ডারে একটা .js ফাইল) — যেমন একটা /api/hello route যা request header পড়ে JSON ফেরত দেয়; এটাই edge-computing লেসনের “dynamic অংশ” — এখন সত্যিকারের একটা V8 isolate আপনার কোড চালাবে
  2. একটা real custom domain (নিজের বা টেস্ট-এর জন্য একটা subdomain) যোগ করে HTTPS provisioning শেষ পর্যন্ত দেখুন
  3. দুই-তিনটা ভিন্ন geographic location থেকে (VPN, অথবা WonderNetwork-জাতীয় public latency-test tool ব্যবহার করে) live URL-এর load latency মেপে edge-CDN effect-টা সংখ্যায় প্রমাণ করুন
  4. Pipeline-এ একটা build-time check যোগ করুন — npm run check (Astro-র নিজস্ব type/content check) build command-এর আগে চালিয়ে, ভাঙা content merge হওয়ার আগেই আটকান
  5. dist/-এর total size আর file count সময়ের সাথে ট্র্যাক করুন (প্রতিটা deploy-এ), আর একটা threshold-এর বেশি বাড়লে সতর্ক করার একটা ছোট script লিখুন
  6. 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 workflowProduction touch না করে review করার অভ্যাস, যেকোনো টিমে
curl -I দিয়ে response header পড়াProduction incident-এ caching/CDN সমস্যা দ্রুত নির্ণয় করা