অনেক অ্যাপ্লিকেশান প্রথম পৃষ্ঠা লোডের সমস্ত ব্যবহারকারীদের কাছে একই বিষয়বস্তু পরিবেশন করে। উদাহরণস্বরূপ একটি নিউজ সাইট সর্বশেষ খবর দেখাতে পারে, অথবা একটি ই-কমার্স সাইট সবচেয়ে বেশি বিক্রি হওয়া আইটেমগুলি দেখাতে পারে।
যদি এই বিষয়বস্তুটি Cloud Firestore থেকে পরিবেশিত হয়, প্রতিটি ব্যবহারকারী যখন অ্যাপ্লিকেশনটি লোড করবে তখন একই ফলাফলের জন্য একটি নতুন ক্যোয়ারী ইস্যু করবে৷ যেহেতু এই ফলাফলগুলি ব্যবহারকারীদের মধ্যে ক্যাশে করা হয় না, তাই অ্যাপ্লিকেশনটি প্রয়োজনের তুলনায় ধীর এবং ব্যয়বহুল।
সমাধান: বান্ডিল
Cloud Firestore বান্ডেলগুলি আপনাকে Firebase অ্যাডমিন SDK ব্যবহার করে ব্যাকএন্ডে সাধারণ ক্যোয়ারী ফলাফল থেকে ডেটা বান্ডেলগুলিকে একত্রিত করার অনুমতি দেয় এবং একটি CDN-এ ক্যাশে করা এই প্রাক-গণনা করা ব্লবগুলি পরিবেশন করে৷ এটি আপনার ব্যবহারকারীদের অনেক দ্রুত প্রথম লোড অভিজ্ঞতা দেয় এবং আপনার Cloud Firestore ক্যোয়ারী খরচ কমিয়ে দেয়।
এই নির্দেশিকায় আমরা Cloud Functions ব্যবহার করব বান্ডেল তৈরি করতে এবং Firebase Hosting গতিশীলভাবে ক্যাশে করতে এবং বান্ডেল সামগ্রী পরিবেশন করতে। বান্ডিল সম্পর্কে আরও তথ্য গাইডগুলিতে উপলব্ধ।
50টি সর্বশেষ "গল্প" অনুসন্ধান করতে প্রথমে একটি সাধারণ পাবলিক HTTP ফাংশন তৈরি করুন এবং ফলাফলটি একটি বান্ডেল হিসাবে পরিবেশন করুন৷
Node.js
exports.createBundle = functions.https.onRequest(async (request, response) => { // Query the 50 latest stories const latestStories = await db.collection('stories') .orderBy('timestamp', 'desc') .limit(50) .get(); // Build the bundle from the query results const bundleBuffer = db.bundle('latest-stories') .add('latest-stories-query', latestStories) .build(); // Cache the response for up to 5 minutes; // see https://firebase.google.com/docs/hosting/manage-cache response.set('Cache-Control', 'public, max-age=300, s-maxage=600'); response.end(bundleBuffer); });
জাভা
package com.example; import com.google.auth.oauth2.GoogleCredentials; import com.google.cloud.firestore.Firestore; import com.google.cloud.firestore.FirestoreBundle; import com.google.cloud.firestore.Query.Direction; import com.google.cloud.firestore.QuerySnapshot; import com.google.cloud.functions.HttpFunction; import com.google.cloud.functions.HttpRequest; import com.google.cloud.functions.HttpResponse; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; import com.google.firebase.cloud.FirestoreClient; import java.io.BufferedWriter; import java.io.IOException; public class ExampleFunction implements HttpFunction { public static FirebaseApp initializeFirebase() throws IOException { if (FirebaseApp.getApps().isEmpty()) { FirebaseOptions options = FirebaseOptions.builder() .setCredentials(GoogleCredentials.getApplicationDefault()) .setProjectId("YOUR-PROJECT-ID") .build(); FirebaseApp.initializeApp(options); } return FirebaseApp.getInstance(); } @Override public void service(HttpRequest request, HttpResponse response) throws Exception { // Get a Firestore instance FirebaseApp app = initializeFirebase(); Firestore db = FirestoreClient.getFirestore(app); // Query the 50 latest stories QuerySnapshot latestStories = db.collection("stories") .orderBy("timestamp", Direction.DESCENDING) .limit(50) .get() .get(); // Build the bundle from the query results FirestoreBundle bundle = db.bundleBuilder("latest-stores") .add("latest-stories-query", latestStories) .build(); // Cache the response for up to 5 minutes // see https://firebase.google.com/docs/hosting/manage-cache response.appendHeader("Cache-Control", "public, max-age=300, s-maxage=600"); // Write the bundle to the HTTP response BufferedWriter writer = response.getWriter(); writer.write(new String(bundle.toByteBuffer().array())); } }
পরবর্তীতে firebase.json
পরিবর্তন করে এই ক্লাউড ফাংশনটি পরিবেশন ও ক্যাশে করার জন্য Firebase হোস্টিং কনফিগার করুন। এই কনফিগারেশনের মাধ্যমে Firebase Hosting CDN ক্লাউড ফাংশন দ্বারা সেট করা ক্যাশে সেটিংস অনুযায়ী বান্ডেল সামগ্রী পরিবেশন করবে। ক্যাশে মেয়াদ শেষ হয়ে গেলে এটি আবার ফাংশন ট্রিগার করে বিষয়বস্তু রিফ্রেশ করবে।
firebase.json
{
"hosting": {
// ...
"rewrites": [{
"source": "/createBundle",
"function": "createBundle"
}]
},
// ...
}
অবশেষে আপনার ওয়েব অ্যাপ্লিকেশনে, CDN থেকে বান্ডিল করা বিষয়বস্তু আনুন এবং Firestore SDK-এ লোড করুন।
// If you are using module bundlers.
import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/firestore/bundle" // This line enables bundle loading as a side effect.
async function fetchFromBundle() {
// Fetch the bundle from Firebase Hosting, if the CDN cache is hit the 'X-Cache'
// response header will be set to 'HIT'
const resp = await fetch('/createBundle');
// Load the bundle contents into the Firestore SDK
await db.loadBundle(resp.body);
// Query the results from the cache
// Note: omitting "source: cache" will query the Firestore backend.
const query = await db.namedQuery('latest-stories-query');
const storiesSnap = await query.get({ source: 'cache' });
// Use the results
// ...
}
আনুমানিক সঞ্চয়
একটি সংবাদ ওয়েবসাইট বিবেচনা করুন যা প্রতিদিন 100,000 ব্যবহারকারী পায় এবং প্রতিটি ব্যবহারকারী প্রাথমিক লোডে একই 50 টি শীর্ষ খবর লোড করে। কোনো ক্যাশিং ছাড়াই, এর ফলে Cloud Firestore থেকে প্রতিদিন 50 x 100,000 = 5,000,000 নথি পড়া হবে।
এখন ধরে নিন সাইটটি উপরের কৌশলটি গ্রহণ করে এবং সেই 50টি ফলাফলকে 5 মিনিট পর্যন্ত ক্যাশ করে। তাই প্রতিটি ব্যবহারকারীর জন্য প্রশ্নের ফলাফল লোড করার পরিবর্তে, ফলাফলগুলি প্রতি ঘন্টায় ঠিক 12 বার লোড হয়। সাইটে যত ব্যবহারকারীই আসুক না কেন, ক্লাউড ফায়ারস্টোরের প্রশ্নের সংখ্যা একই থাকে। 5,000,000 নথি পড়ার পরিবর্তে, এই পৃষ্ঠাটি প্রতিদিন 12 x 24 x 50 = 14,400 নথি পাঠ করবে। Firebase হোস্টিং এবং Cloud Functions জন্য ছোট অতিরিক্ত খরচগুলি সহজেই Cloud Firestore খরচ সঞ্চয় দ্বারা অফসেট করা হয়।
যদিও বিকাশকারী খরচ সঞ্চয় থেকে উপকৃত হয়, সবচেয়ে বেশি সুবিধাভোগী হল ব্যবহারকারী। সরাসরি Cloud Firestore পরিবর্তে Firebase হোস্টিং CDN থেকে এই 50টি নথি লোড করলে পৃষ্ঠার সামগ্রী লোডের সময় থেকে 100-200ms বা তার বেশি শেভ করা যায়। গবেষণায় বারংবার দেখা গেছে যে দ্রুত গতির পৃষ্ঠার অর্থ সুখী ব্যবহারকারী।