পর্ব ৮-এ KV দিয়ে ম্যানুয়ালি ক্যাশিং করেছিলাম। কিন্তু Cloudflare-এর একটা আরও সরাসরি টুল আছে এই কাজের জন্য — Cache API, যা পুরো HTTP রেসপন্স ক্যাশ করে, আর Cache-Control হেডার, যা ব্রাউজার ও Cloudflare-এর নিজস্ব CDN-কে বলে দেয় কতক্ষণ কিছু ক্যাশ রাখতে হবে। এই পর্বে শিখব কীভাবে সাইট দ্রুত করা যায় প্র্যাকটিক্যালি।
তিন স্তরের ক্যাশিং
একটা রিকোয়েস্ট যখন আসে, তিনটা জায়গায় ক্যাশ চেক হতে পারে —
- ব্রাউজার ক্যাশ — ইউজারের নিজের ডিভাইসে সেভ থাকে, দ্বিতীয়বার একই সাইটে এলে নেটওয়ার্কই লাগে না
- Cloudflare Edge Cache (CDN) — Cloudflare-এর কাছের সার্ভারে সেভ থাকে, অরিজিন সার্ভার পর্যন্ত যাওয়া লাগে না
- Worker-এর নিজস্ব Cache API / KV — কোডের ভেতর ম্যানুয়ালি নিয়ন্ত্রণ করা ক্যাশ (পর্ব ৮-এর মতো)
Cache-Control হেডার — বেসিক
যেকোনো রেসপন্সে একটা হেডার যোগ করে বলে দেওয়া যায় কতক্ষণ ক্যাশ রাখতে হবে।
export default {
async fetch(request, env, ctx) {
const data = { books: ["অপরাজিত", "পথের পাঁচালী"] };
return new Response(JSON.stringify(data), {
headers: {
"content-type": "application/json",
"Cache-Control": "public, max-age=300", // ৫ মিনিট ক্যাশ
},
});
},
};
এখানে public মানে যে কেউ (ব্রাউজার, Cloudflare CDN) ক্যাশ করতে পারবে, max-age=300 মানে ৩০০ সেকেন্ড (৫ মিনিট) পর্যন্ত ক্যাশ বৈধ।
কোন কনটেন্টে কেমন Cache-Control
| কনটেন্ট টাইপ | উদাহরণ | প্রস্তাবিত |
|---|---|---|
| ছবি, ফন্ট, CSS/JS বান্ডেল | book-cover.jpg | max-age=31536000, immutable (১ বছর) |
| ব্লগ পোস্ট, স্ট্যাটিক পেজ | /blog/firebase-part-1 | max-age=3600 (১ ঘণ্টা) |
| প্রায়ই বদলানো API ডেটা | /api/books | max-age=60 (১ মিনিট) |
| ইউজার-নির্দিষ্ট, সেনসিটিভ | /api/my-profile | private, no-store (ক্যাশ না করা) |
immutable মানে — এই ফাইলের কনটেন্ট কখনো বদলাবে না (সাধারণত ফাইলের নামে একটা hash যোগ করে এটা নিশ্চিত করা হয়, যেমন app.a1b2c3.js), তাই ব্রাউজার এমনকি রিফ্রেশ চেকও করবে না।
Worker-এর Cache API — নিজে থেকে ক্যাশ ব্যবস্থাপনা
শুধু হেডার সেট করার বাইরে, Worker কোড থেকেই সরাসরি ক্যাশ চেক ও সেভ করা যায় — পর্ব ৮-এর KV-ভিত্তিক ক্যাশিং-এর চেয়ে এটা হেডারসহ পুরো রেসপন্স সেভ করে।
export default {
async fetch(request, env, ctx) {
const cache = caches.default;
const cacheKey = new Request(request.url, request);
// প্রথমে ক্যাশে আছে কিনা দেখা
let response = await cache.match(cacheKey);
if (response) {
return response; // ক্যাশ থেকে সরাসরি ফেরত
}
// না থাকলে আসল ডেটা তৈরি করা
const data = { books: ["অপরাজিত"] };
response = new Response(JSON.stringify(data), {
headers: {
"content-type": "application/json",
"Cache-Control": "public, max-age=300",
},
});
// ক্যাশে সেভ করা (ব্যাকগ্রাউন্ডে, রেসপন্স আটকে না রেখে)
ctx.waitUntil(cache.put(cacheKey, response.clone()));
return response;
},
};
লক্ষ্য করুন — response.clone() ব্যবহার হচ্ছে, কারণ একটা Response একবারই পড়া যায় — একই রেসপন্স ইউজারকে পাঠানো আর ক্যাশে সেভ করা দুটোর জন্যই আলাদা কপি লাগে। ctx.waitUntil() Worker-কে বলে দেয় — রেসপন্স পাঠানোর পরও ব্যাকগ্রাউন্ডে ক্যাশ সেভের কাজ শেষ করতে দাও।
Cache Purge — জোর করে পুরনো ক্যাশ মুছে ফেলা
ধরা যাক একটা বইয়ের তথ্য আপডেট হয়েছে, কিন্তু পুরনো ক্যাশড ভার্সন এখনো দেখাচ্ছে। Cloudflare Dashboard থেকে ম্যানুয়ালি purge করা যায় —
- Caching → Configuration → Purge Cache-এ যান
- Custom Purge দিয়ে নির্দিষ্ট URL, অথবা Purge Everything দিয়ে সব মুছে ফেলা যায়
প্রোগ্রাম্যাটিকভাবেও API দিয়ে purge করা যায় — যেমন একটা বই আপডেট হলে GitHub Actions ওয়ার্কফ্লো থেকেই (পর্ব ২) স্বয়ংক্রিয়ভাবে সেই URL-এর ক্যাশ পার্জ করে দেওয়া।
অন্যান্য Performance টিপস
- ছবি অপটিমাইজেশন — Cloudflare-এর Image Resizing/Polish ফিচার দিয়ে ছবি স্বয়ংক্রিয়ভাবে সংকুচিত ও সঠিক ফরম্যাটে (WebP) পরিবেশন করা যায়
- Brotli/Gzip কম্প্রেশন — Cloudflare ডিফল্টভাবেই টেক্সট-ভিত্তিক কনটেন্ট (HTML, CSS, JS) কম্প্রেস করে পাঠায়, বাড়তি কিছু করতে হয় না
- HTTP/3 ও QUIC — Cloudflare স্বয়ংক্রিয়ভাবে সাপোর্ট করে, দ্রুততর কানেকশনের জন্য
ইন্টারেক্টিভ — Cache Hit রেসপন্স টাইম
নিচে দেখো ভিন্ন ভিন্ন max-age সেটিং কীভাবে বারবার রিকোয়েস্টের গড় রেসপন্স টাইম কমায়।
ভালো অভ্যাস
- ইউজার-নির্দিষ্ট ডেটা কখনো পাবলিকভাবে ক্যাশ করবেন না —
privateবাno-storeব্যবহার করুন, নাহলে একজনের ডেটা আরেকজন দেখে ফেলতে পারে - স্ট্যাটিক অ্যাসেটে দীর্ঘ ক্যাশ + ফাইলনামে hash — আপডেট হলে ফাইলের নাম বদলে যায়, তাই পুরনো ক্যাশ সমস্যা করে না
- যতটা সম্ভব দীর্ঘ max-age ব্যবহার করুন যেখানে ডেটা কম বদলায়, কিন্তু কখনো "খুব বেশি নিরাপদ থাকতে" ছোট max-age রাখারও দরকার নেই যদি Purge API ব্যবহারের সুযোগ থাকে
নিজে চেষ্টা করো
Exercise:
- নিজের Worker-এ একটা রেসপন্সে
Cache-Control: public, max-age=60যোগ করো, ব্রাউজার DevTools-এর Network ট্যাবে গিয়ে হেডার চেক করো। - উপরের Cache API প্যাটার্ন দিয়ে একটা Worker বানাও, প্রথমবার আর দ্বিতীয়বার রিকোয়েস্টের সময় তুলনা করো।
- Cloudflare Dashboard-এ গিয়ে একটা নির্দিষ্ট URL-এর ক্যাশ ম্যানুয়ালি Purge করো।
- নিজের কোনো প্রজেক্টের বিভিন্ন কনটেন্ট (ছবি, API, পেজ) তালিকা করে প্রতিটার জন্য উপযুক্ত
max-ageঠিক করো।
পরের পর্বে যা থাকছে
পরের পর্বে আমরা শিখব Security — Rate Limiting ও WAF বেসিক — কীভাবে বট বা অতিরিক্ত রিকোয়েস্ট থেকে নিজের API সুরক্ষিত রাখা যায়, আর Cloudflare-এর Web Application Firewall কীভাবে কাজ করে।