SSR (সার্ভার-সাইড রেন্ডারিং) সহ ডায়নামিক ওয়েব অ্যাপে Firebase ব্যবহার করা

আপনি যদি Firebase JS SDK বা অন্যান্য Firebase ক্লায়েন্ট SDK-এর সাথে কাজ করে থাকেন, তাহলে আপনি সম্ভবত FirebaseApp ইন্টারফেস এবং অ্যাপ ইনস্ট্যান্স কনফিগার করতে এটি কীভাবে ব্যবহার করবেন তার সাথে পরিচিত। সার্ভার সাইডে একই ধরনের অপারেশন সহজ করতে, Firebase FirebaseServerApp প্রদান করে।

FirebaseServerApp হল FirebaseApp-এর একটি ভেরিয়েন্ট যা সার্ভার-সাইড রেন্ডারিং (SSR) এনভায়রনমেন্টে ব্যবহার করা হয়। এতে Firebase সেশন চালিয়ে যাওয়ার টুল অন্তর্ভুক্ত আছে যা ক্লায়েন্ট-সাইড রেন্ডারিং (CSR) / সার্ভার-সাইড রেন্ডারিং ডিভাইড জুড়ে বিস্তৃত। এইসব টুল ও স্ট্র্যাটেজি Firebase-এর মাধ্যমে তৈরি করা এবং Firebase App Hosting-এর মতো Google এনভায়রনমেন্টে ডিপ্লয় করা ডায়নামিক ওয়েব অ্যাপ উন্নত করতে সাহায্য করতে পারে।

এগুলি করার জন্য FirebaseServerApp ব্যবহার করুন:

  • ব্যবহারকারী প্রসঙ্গে সার্ভার-সাইড কোড এক্সিকিউট করুন, যা Firebase অ্যাডমিন SDK-এর থেকে আলাদা, কারণ Firebase অ্যাডমিন SDK-এর সম্পূর্ণ অ্যাডমিনিস্ট্রেশন অধিকার আছে।
  • SSR এনভায়রনমেন্টে App Check-এর ব্যবহার চালু করুন।
  • ক্লায়েন্টে তৈরি করা Firebase Auth সেশন চালিয়ে যান।

FirebaseServerApp লাইফসাইকেল

সার্ভার-সাইড রেন্ডারিং (SSR) ফ্রেমওয়ার্ক এবং অন্যান্য নন-ব্রাউজার রানটাইম যেমন ক্লাউড ওয়ার্কাররা একাধিক এক্সিকিউশন জুড়ে রিসোর্স পুনরায় ব্যবহার করে ইনিশিয়ালাইজেশন টাইম অপ্টিমাইজ করে। FirebaseServerApp-কে এমনভাবে ডিজাইন করা হয়েছে যাতে রেফারেন্স কাউন্ট মেকানিজম ব্যবহার করে এইসব এনভায়রনমেন্টে কাজ করতে পারে। কোনও অ্যাপ যদি আগের initializeServerApp-এর মতো একই প্যারামিটার সহ initializeServerApp কল করে, তাহলে এটি একই FirebaseServerApp ইনস্ট্যান্স পায় যা আগে থেকেই ইনিশিয়ালাইজ করা ছিল। এটি অপ্রয়োজনীয় ইনিশিয়ালাইজেশন ওভারহেড ও মেমরি অ্যালোকেশন কমায়। deleteApp-কে FirebaseServerApp ইনস্ট্যান্সে ইনভোক করা হলে, এটি রেফারেন্স কাউন্ট কমায় এবং রেফারেন্স কাউন্ট শূন্যে পৌঁছানোর পরে ইনস্ট্যান্সটি ফ্রি হয়ে যায়।

FirebaseServerAppটি ইনস্ট্যান্স ক্লিন-আপ করা হচ্ছে

FirebaseServerApp ইনস্ট্যান্সে কখন deleteApp কল করতে হবে তা জানা কঠিন হতে পারে, বিশেষ করে আপনি যদি সমান্তরালভাবে অনেক অ্যাসিঙ্ক্রোনাস অপারেশন চালান। FirebaseServerAppSettings-এর releaseOnDeref ফিল্ড এটি সহজ করতে সাহায্য করে। আপনি যদি অনুরোধের স্কোপের লাইফস্প্যান (যেমন, SSR অনুরোধের হেডার অবজেক্ট) সহ কোনও অবজেক্টে releaseOnDeref-এর রেফারেন্স অ্যাসাইন করেন, তাহলে ফ্রেমওয়ার্ক হেডার অবজেক্ট রিক্লেম করার সময় FirebaseServerApp তার রেফারেন্সের সংখ্যা কমাবে। এটি আপনার FirebaseServerApp ইনস্ট্যান্স অটোমেটিক ক্লিন-আপ করে।

releaseOnDeref-এর ব্যবহারের একটি উদাহরণ এখানে দেওয়া হল:

/// Next.js
import { headers } from 'next/headers'
import { FirebaseServerAppSettings, initializeServerApp} from "firebase/app";

export default async function Page() {
  const headersObj = await headers();
  let appSettings: FirebaseServerAppSettings = {};
  appSettings.releaseOnDeref = headersObj;
  const serverApp = initializeServerApp(firebaseConfig, appSettings);
  ...
}

ক্লায়েন্টে তৈরি করা যাচাইকৃত সেশন আবার চালু করুন

Auth আইডি টোকেন দিয়ে FirebaseServerApp-এর ইনস্ট্যান্স শুরু করা হলে, এটি ক্লায়েন্ট-সাইড রেন্ডারিং (CSR) এবং সার্ভার-সাইড রেন্ডারিং (SSR) এনভায়রনমেন্টের মধ্যে যাচাই করা ব্যবহারকারীর সেশন ব্রিজ করার সুবিধা চালু করে। Firebase Auth SDK-এর ইনস্ট্যান্স FirebaseServerApp অবজেক্টের সাথে শুরু করা হয়েছে যাতে Auth ID টোকেন আছে। এটি শুরু করার সময় ব্যবহারকারীকে সাইন-ইন করানোর চেষ্টা করবে। এর জন্য অ্যাপ্লিকেশনকে কোনও সাইন-ইন পদ্ধতি চালু করতে হবে না।

Auth আইডি টোকেন প্রদান করলে, অ্যাপ ক্লায়েন্টে Auth-এর যেকোনও সাইন-ইন পদ্ধতি ব্যবহার করতে পারে। এর ফলে, সার্ভার-সাইডে সেশন চালিয়ে যাওয়া নিশ্চিত করা যায়, এমনকি যেসব সাইন-ইন পদ্ধতিতে ব্যবহারকারীর ইন্টার‍্যাকশন প্রয়োজন, সেগুলির ক্ষেত্রেও। এছাড়াও, এটি সার্ভারে ইনটেনসিভ অপারেশন অফলোড করার সুবিধা দেয়, যেমন যাচাই করা Firestore কোয়েরি, যা আপনার অ্যাপের রেন্ডারিং পারফর্ম্যান্স উন্নত করবে।

/// Next.js
import { initializeServerApp } from "firebase/app";
import { getAuth } from "firebase/auth";

// Replace the following with your app's
// Firebase project configuration
const firebaseConfig = {
  // ...
};

const firebaseServerAppSettings = {
  authIdToken: token  // See "Pass client tokens to the server side
                      // rendering phase" for an example on how transmit
                      // the token from the client and the server.
}

const serverApp =
  initializeServerApp(firebaseConfig,
                      firebaseServerAppSettings);
const serverAuth = getAuth(serverApp);

// FirebaseServerApp and Auth will now attempt
// to sign in the current user based on provided
// authIdToken.

SSR এনভায়রনমেন্টে App Check ব্যবহার করা

App Check এনফোর্সমেন্ট, App Check SDK ইনস্ট্যান্সের উপর নির্ভর করে যা Firebase SDK, getToken-কে ইন্টার্নালি কল করার জন্য ব্যবহার করে। এর ফলে যে টোকেন তৈরি হয়, সেটি সব Firebase পরিষেবার অনুরোধে অন্তর্ভুক্ত করা হয়, যাতে ব্যাকএন্ড অ্যাপটি যাচাই করতে পারে।

তবে, অ্যাপ যাচাইকরণের জন্য নির্দিষ্ট হিউরিস্টিক অ্যাক্সেস করতে App Check SDK-এর একটি ব্রাউজার প্রয়োজন, তাই এটি সার্ভার এনভায়রনমেন্টে শুরু করা যাবে না।

FirebaseServerApp একটি বিকল্প প্রদান করে। FirebaseServerApp ইনিশিয়ালাইজেশনের সময় ক্লায়েন্টের তৈরি করা App Check টোকেন প্রদান করা হলে, Firebase পরিষেবা কল করার সময় Firebase প্রোডাক্ট SDK এটি ব্যবহার করবে, যার ফলে App Check SDK ইনস্ট্যান্সের প্রয়োজন হবে না।

/// Next.js
import { initializeServerApp } from "firebase/app";

// Replace the following with your app's
// Firebase project configuration
const firebaseConfig = {
  // ...
};

const firebaseServerAppSettings = {
  appCheckToken: token // See "Pass client tokens to the server side
                       // rendering phase" for an example on how transmit
                       // the token from the client and the server.
}

const serverApp =
  initializeServerApp(firebaseConfig,
                      firebaseServerAppSettings);

// The App Check token will now be appended to all Firebase service requests.

সার্ভার-সাইড রেন্ডারিং ফেজে ক্লায়েন্ট টোকেন পাস করুন

ক্লায়েন্ট থেকে সার্ভার-সাইড রেন্ডারিং (SSR) ফেজে যাচাই করা Auth ID টোকেন (এবং App Check টোকেন) ট্রান্সমিট করতে, সার্ভিস ওয়ার্কার ব্যবহার করুন। এই পদ্ধতিতে SSR ট্রিগার করে এমন ফেচ অনুরোধ ইন্টারসেপ্ট করা এবং অনুরোধের হেডারে টোকেন যোগ করা হয়।

Firebase Auth সার্ভিস ওয়ার্কারের রেফারেন্স ইমপ্লিমেন্টেশনের জন্য সার্ভিস ওয়ার্কারের সাথে সেশন ম্যানেজমেন্ট দেখুন। এছাড়াও, FirebaseServerApp ইনিশিয়ালাইজেশনে ব্যবহারের জন্য হেডার থেকে এইসব টোকেন কীভাবে পার্স করতে হয় তা দেখানো কোডের জন্য সার্ভার সাইড পরিবর্তন দেখুন।

SSR এনভায়রনমেন্টে Firestore ব্যবহার করা

সার্ভার-সাইড রেন্ডারিং (SSR) সহ ওয়েব অ্যাপ্লিকেশন তৈরি করার সময়, পারফর্ম্যান্স ও ব্যবহারকারীর অভিজ্ঞতা অপ্টিমাইজ করার জন্য আপনাকে প্রায়ই সার্ভার ও ক্লায়েন্টের মধ্যে ডেটা শেয়ার করতে হয়। Firestore SDK সিরিয়ালাইজেশন টুল প্রদান করে যা আপনাকে সার্ভারে স্ন্যাপশট ও নির্দিষ্ট ডেটার ধরন ক্যাপচার করতে এবং সরাসরি আপনার ক্লায়েন্ট-সাইড কম্পোনেন্টে সেগুলি পাস করতে দেয়। এই প্রসেসটি SSR ফেজের সময় প্রি-ফেচ করা ডেটা ব্যবহার করে ক্লায়েন্টকে হাইড্রেট স্টেট করার সুবিধা দেওয়ার মাধ্যমে অপ্রয়োজনীয় ফেচ করার প্রসেসকে বাতিল করে দেয়। এছাড়াও, আপনি এই সিরিয়ালাইজ করা স্টেট থেকে রিয়েল-টাইম লিসনারে ট্রানজিশন করতে পারবেন, যা আপনার অ্যাপ্লিকেশনকে ডেটাবেসের সাথে সিঙ্ক করে রাখবে।

সার্ভার-সাইড রেন্ডারিং (SSR) ফেজের সময় ক্লায়েন্ট-সাইড কম্পোনেন্টের মধ্যে থেকে উদ্ধার করা ডেটা কীভাবে আবার ব্যবহার করা যায় তা এই বিভাগে বর্ণনা করা হয়েছে।

ডেটার ধরন সিরিয়ালাইজ করুন

নির্দিষ্ট কিছু Firestore ডেটার ধরন তাদের ডেটাকে সিরিয়ালাইজ করা যায় এমন ফর্ম্যাটে পরিবর্তন করার জন্য toJSON পদ্ধতি প্রদান করে। এর মধ্যে Bytes, GeoPoint, Timestamp ও VectorValue-এর মতো অবজেক্টের উদাহরণ অন্তর্ভুক্ত।

JSON ফর্ম্যাটে ডেটা পাওয়ার পরে, আপনি স্ট্যান্ডার্ড ফ্রেমওয়ার্ক মেকানিজমের মাধ্যমে সার্ভার থেকে ক্লায়েন্টে অথবা ডিভাইড স্প্যান করে এমন কম্পোনেন্টের প্যারামিটার হিসেবে এটি পাস করতে পারবেন। যেমন:

import {
  Bytes
} from 'firebase/firestore';

const BYTES_DATA = new Uint8Array([0, 1, 2, 3, 4, 5]);
const bytes = Bytes.fromUint8Array(BYTES_DATA);
const bytesJSON = bytes.toJSON();

ডেটার ধরন ডিসিরিয়ালাইজ করুন

Firestore ডেটার ধরনের মধ্যে স্ট্যাটিক পদ্ধতি fromJSON অন্তর্ভুক্ত থাকে যা সিরিয়ালাইজ করা ডেটাকে অপারেট করা যায় এমন Firestore ডেটার ধরনে পরিবর্তন করে।

যেমন, নিম্নলিখিত কোডটি Bytes ডেটা টাইপকে ডিসিরিয়ালাইজ করে:

import {
  Bytes
} from 'firebase/firestore';

// Assuming the same `bytesJSON` variable from the previous example.
const deserializedBytes = Bytes.fromJSON(bytesJSON);

Firestore স্ন্যাপশট সিরিয়ালাইজ ও ডিসিরিয়ালাইজ করা

Firestore ডেটার ধরনের মতো, আপনি toJSON ব্যবহার করে DocumentSnapshot এবং QuerySnapshot-এর ইনস্ট্যান্স সিরিয়ালাইজ করতে পারবেন। তবে, এগুলি ডিসিরিয়ালাইজ করতে, আপনাকে স্ট্যাটিক fromJSON পদ্ধতির পরিবর্তে স্ট্যান্ডঅ্যালোন ফাংশন documentSnapshotFromJSON এবং querySnapshotFromJSON ব্যবহার করতে হবে।

যেমন, query অপারেশনের querySnapshot ফলাফল toJSON পদ্ধতি ব্যবহার করে সিরিয়ালাইজ করা যেতে পারে:

import {
  collection,
  getDocs,
  query,
  querySnapshotFromJSON
} from 'firebase/firestore';
// Assuming a configured instance of Firestore in the variable `firestore`.
const queryRef = query(collection(firestore, QUERY_PATH));
const querySnapshot = await getDocs(queryRef);
const querySnapshotJson = querySnapshot.toJSON();

তারপর, এই ডেটা ডিসিরিয়ালাইজ করা যেতে পারে:

import {
  querySnapshotFromJSON
} from 'firebase/firestore';

// deserializedSnapshot is an object of type QuerySnapshot:

const deserializedSnapshot =
  querySnapshotFromJSON(firestore, querySnapshotJson);

সিরিয়ালাইজড স্ন্যাপশট সহ লিসনার

SSR ফেজের সময় কোয়েরি করা ডেটা আপনার প্রাথমিক CSR রেন্ডারের জন্য মূল্যবান হলেও, আপনাকে হয়ত সেই তথ্যের রিয়েল-টাইম আপডেটের জন্য Firestore পরিষেবা মনিটর করতে হবে।

আপনার অ্যাপে যদি এই রিয়েল-টাইম আপডেট প্রয়োজন হয়, তাহলে আপনি onSnapshotResume ফাংশন ব্যবহার করে সিরিয়ালাইজ করা Snapshot ডেটা সহ Firestore SnapshotListeners ইনিশিয়ালাইজ করতে পারবেন। যেমন:

const observer = {
  next: (qs) => {
    console.log("onSnapshot invoked: ", qs.data());
  },
  error: (e) => {
    console.log("error callback invoked: ", e.toString());
  }
};
const unsubscribe = onSnapshotResume(firestore, querySnapshotJson, observer);