এতদিন যা করেছি তার সবই ছিল ক্লায়েন্ট-সাইড — ব্রাউজার থেকে সরাসরি Firebase-এর সাথে কথা বলা। কিন্তু কিছু কাজ আছে যা ব্রাউজার থেকে করা ঠিক না — যেমন সিক্রেট API কী ব্যবহার করা, ইমেইল পাঠানো, বা ডেটা পরিবর্তনের ওপর ভিত্তি করে অটোমেটিক অ্যাকশন চালানো। এই কাজের জন্য আছে Cloud Functions — Firebase-এর সার্ভার-সাইড কোড চালানোর সিস্টেম।
Cloud Functions কী?
এটা মূলত ছোট ছোট Node.js ফাংশন, যা Google-এর সার্ভারে চলে, আর নির্দিষ্ট কোনো ইভেন্টে (trigger) নিজে থেকে চালু হয়ে যায় — কোনো সার্ভার নিজে ম্যানেজ করা লাগে না।
- HTTP trigger — একটা URL কল করলে ফাংশন চলে (নিজের API বানানোর মতো)
- Database trigger — RTDB-তে কোনো ডেটা লেখা/বদলানো/মুছার সাথে সাথে চলে
- Auth trigger — নতুন ইউজার সাইন আপ করলে চলে
গুরুত্বপূর্ণ: Cloud Functions ব্যবহার করতে হলে Firebase প্রজেক্ট Blaze plan-এ (pay-as-you-go) থাকতে হবে — যদিও এখানেও একটা বড় ফ্রি কোটা আছে, ছোট প্রজেক্টে সাধারণত বিল আসে না।
Functions সেটআপ করা
# পর্ব ১০-এর firebase init-এ Functions অপশন বেছে নিতে হবে firebase init functions # এটা একটা functions/ ফোল্ডার বানাবে cd functions npm install
HTTP Trigger — নিজের API বানানো
সবচেয়ে সহজ উদাহরণ — একটা URL, যেটা কল করলে একটা রেসপন্স দেয়।
// functions/index.js
const { onRequest } = require("firebase-functions/v2/https");
exports.hello = onRequest((req, res) => {
res.send("Firebase Functions থেকে সালাম!");
});
// ডেপ্লয়ের পর একটা URL পাওয়া যাবে, যেমন:
// https://hello-xxxxx.a.run.app
এই প্যাটার্নটা কাজে লাগে যখন এমন কিছু করতে হয় যা ব্রাউজারে করা নিরাপদ না — যেমন একটা পেমেন্ট গেটওয়ে API কল করা, যেখানে একটা সিক্রেট কী ব্যবহার করতে হয় যা ফ্রন্টএন্ড কোডে কখনো রাখা ঠিক না।
Database Trigger — ডেটা বদলালে অটোমেটিক অ্যাকশন
এটাই Cloud Functions-এর সবচেয়ে শক্তিশালী ব্যবহার — RTDB-তে কিছু ঘটলেই সার্ভার-সাইড কোড নিজে থেকে চলে। ধরা যাক নতুন বই যোগ হলে সেই বইয়ের একটা "created" timestamp আর slug অটোমেটিক জেনারেট করতে চাই।
// functions/index.js
const { onValueCreated } = require("firebase-functions/v2/database");
const { getDatabase } = require("firebase-admin/database");
const { initializeApp } = require("firebase-admin/app");
initializeApp();
exports.onNewBook = onValueCreated("/books/{bookId}", async (event) => {
const bookId = event.params.bookId;
const bookData = event.data.val();
const slug = bookData.title.toLowerCase().replace(/\s+/g, "-");
await getDatabase().ref(`books/${bookId}`).update({
slug,
createdAt: Date.now(),
});
console.log(`নতুন বই প্রসেস হলো: ${bookData.title}`);
});
লক্ষ্য করুন — /books/{bookId}-এর {bookId} একটা wildcard, ঠিক পর্ব ৮-এর Security Rules-এর $bookId-এর মতোই কাজ করে — যেকোনো নতুন বই যোগ হলেই event.params.bookId-এ সেই ID পাওয়া যাবে।
এখানে firebase-admin ব্যবহার হচ্ছে — এটা ফ্রন্টএন্ড SDK থেকে আলাদা, Security Rules বাইপাস করে সরাসরি ডেটাবেজে পূর্ণ অ্যাক্সেস পায় (কারণ এটা সার্ভারে চলে, বিশ্বাসযোগ্য পরিবেশে)।
Auth Trigger — নতুন ইউজারের জন্য ওয়েলকাম ডেটা
পর্ব ২-এর সাইন আপ ফ্লো মনে আছে? একটা Auth trigger দিয়ে প্রতিটা নতুন ইউজারের জন্য অটোমেটিক একটা প্রোফাইল নোড বানানো যায়, ফ্রন্টএন্ড কোডে আলাদা করে সেটা লেখার দরকার পড়ে না।
const { beforeUserCreated } = require("firebase-functions/v2/identity");
const { getDatabase } = require("firebase-admin/database");
exports.onNewUser = beforeUserCreated(async (event) => {
const user = event.data;
await getDatabase().ref(`users/${user.uid}`).set({
email: user.email,
joinedAt: Date.now(),
bookCount: 0,
});
});
ডেপ্লয় করা
firebase deploy --only functions
পর্ব ১০-এ শেখা Emulator দিয়েই Functions লোকালি টেস্ট করা যায় — firebase emulators:start চালালে Functions-ও লোকালি চলে, লাইভে ডেপ্লয় না করেই।
Client-Side কি তাহলে সব ফেলে দিতে হবে?
না — এই সিরিজের বেশিরভাগ কাজ (Auth, সাধারণ Read/Write) ক্লায়েন্ট-সাইড থেকেই সরাসরি করাই ঠিক, Security Rules-ই যথেষ্ট নিরাপত্তা দেয়। Cloud Functions দরকার হয় শুধু —
- সিক্রেট কী ব্যবহার করতে হলে
- একাধিক ইউজার/নোড জুড়ে জটিল, নির্ভরযোগ্য লজিক (যেমন পেমেন্ট প্রসেসিং)
- নির্দিষ্ট ইভেন্টে সবসময় নিশ্চিতভাবে কিছু ঘটাতে হলে, ফ্রন্টএন্ড বন্ধ থাকলেও
ইন্টারেক্টিভ — Database Trigger ফ্লো
নিচে দেখো একটা নতুন বই যোগ করলে কীভাবে ধাপে ধাপে Cloud Function নিজে থেকে চলে।
নিজে চেষ্টা করো
Exercise:
- নিজের প্রজেক্টে
firebase init functionsচালাও, তারপর উপরেরhelloHTTP function Emulator-এ চালিয়ে ব্রাউজারে URL খুলে দেখো। - একটা Database trigger লেখো, যা নতুন বই যোগ হলে অটোমেটিক একটা
createdAtফিল্ড যোগ করবে। - ভাবো — নিজের ArifStack বা Pathok Ghar-এর মতো কোনো প্রজেক্টে কোথায় Cloud Functions সত্যিই দরকার হতে পারে, আর কোথায় শুধু ক্লায়েন্ট-সাইডেই যথেষ্ট।
পরের পর্বে যা থাকছে
এই সিরিজের শেষ পর্বে আমরা সব একসাথে এনে একটা CRUD মিনি-প্রজেক্ট (Todo/Note App) বানাব, আর সেটা Cloudflare Pages-এ Firebase backend সহ কীভাবে ডেপ্লয় করতে হয় তা শিখব — Blaze plan সীমা ও খরচ নিয়ন্ত্রণসহ।