कई ऐप्लिकेशन, पहले पेज लोड होने पर सभी उपयोगकर्ताओं को एक ही कॉन्टेंट दिखाते हैं. उदाहरण के लिए, कोई न्यूज़ साइट, हाल की खबरें दिखा सकती है. वहीं, कोई ई-कॉमर्स साइट, सबसे ज़्यादा बिकने वाले आइटम दिखा सकती है.
अगर यह कॉन्टेंट Cloud Firestore से दिखाया जाता है, तो हर उपयोगकर्ता, ऐप्लिकेशन लोड होने पर एक ही तरह के नतीजों के लिए नई क्वेरी करेगा. ऐसा इसलिए, क्योंकि इन नतीजों को उपयोगकर्ताओं के बीच कैश नहीं किया जाता. इसलिए, ऐप्लिकेशन को लोड होने में ज़्यादा समय लगता है और यह ज़्यादा महंगा होता है.
समस्या हल करने का तरीका: बंडल
Cloud Firestore बंडल की मदद से, Firebase Admin SDK का इस्तेमाल करके, बैकएंड पर सामान्य क्वेरी के नतीजों से डेटा बंडल बनाए जा सकते हैं. साथ ही, इन पहले से कंप्यूट किए गए ब्लॉब को सीडीएन पर कैश किया जा सकता है. इससे, उपयोगकर्ताओं को पहली बार पेज लोड होने पर बेहतर अनुभव मिलता है. साथ ही, आपकी Cloud Firestore क्वेरी की लागत कम होती है.
इस गाइड में, हम बंडल जनरेट करने के लिए Cloud Functions और Firebase Hosting बंडल के कॉन्टेंट को डाइनैमिक तरीके से कैश करने और दिखाने के लिए इस्तेमाल करेंगे. बंडल के बारे में ज़्यादा जानकारी, गाइड में उपलब्ध है.
सबसे पहले, 50 हाल की "कहानियों" की क्वेरी करने और नतीजे को बंडल के तौर पर दिखाने के लिए, एक आसान सार्वजनिक एचटीटीपी फ़ंक्शन बनाएं.
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); });
Java
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 में बदलाव करके, इस Cloud Function को दिखाने और कैश करने के लिए Firebase Hosting को कॉन्फ़िगर करें. इस कॉन्फ़िगरेशन के साथ, Firebase Hosting CDN
Cloud Function की सेट की गई कैश सेटिंग के मुताबिक, बंडल का कॉन्टेंट दिखाएगा. कैश की समयसीमा खत्म होने पर, यह फ़ंक्शन को फिर से ट्रिगर करके कॉन्टेंट को रीफ़्रेश करेगा.
firebase.json
{
"hosting": {
// ...
"rewrites": [{
"source": "/createBundle",
"function": "createBundle"
}]
},
// ...
}
आखिर में, अपने वेब ऐप्लिकेशन में, सीडीएन से बंडल किया गया कॉन्टेंट फ़ेच करें और उसे 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
// ...
}
अनुमानित बचत
मान लें कि कोई न्यूज़ वेबसाइट है, जिसे हर दिन 1,00,000 उपयोगकर्ता ऐक्सेस करते हैं. साथ ही, हर उपयोगकर्ता, पहली बार लोड होने पर, 50 सबसे लोकप्रिय खबरें देखता है. कैश करने की सुविधा न होने पर, इससे हर दिन 50 x 1,00,000 = 50,00,000 दस्तावेज़ पढ़े जाएंगे Cloud Firestore.
अब मान लें कि साइट, ऊपर बताई गई तकनीक अपनाती है और उन 50 नतीजों को पांच मिनट तक कैश करती है. इसलिए, हर उपयोगकर्ता के लिए क्वेरी के नतीजे लोड करने के बजाय, नतीजे हर घंटे में 12 बार लोड किए जाते हैं. साइट पर कितने भी उपयोगकर्ता आएं, Cloud Firestore पर की जाने वाली क्वेरी की संख्या वही रहती है. 50,00,000 दस्तावेज़ पढ़ने के बजाय, इस पेज पर हर दिन 12 x 24 x 50 = 14,400 दस्तावेज़ पढ़े जाएंगे. Firebase Hosting और Cloud Functions के लिए लगने वाली थोड़ी ज़्यादा लागत की भरपाई, Cloud Firestore की लागत में होने वाली बचत से आसानी से हो जाती है.
डेवलपर को लागत में बचत का फ़ायदा मिलता है. हालांकि, सबसे ज़्यादा फ़ायदा उपयोगकर्ता को मिलता है. Cloud Firestore से सीधे लोड करने के बजाय, Firebase Hosting CDN से इन 50 दस्तावेज़ों को लोड करने पर, पेज के कॉन्टेंट को लोड होने में लगने वाले समय में 100 से 200 मिलीसेकंड या उससे ज़्यादा की बचत हो सकती है.Cloud Firestore स्टडी से बार-बार पता चला है कि तेज़ी से लोड होने वाले पेजों से उपयोगकर्ताओं को बेहतर अनुभव मिलता है.