Paketlenmiş Firestore içeriklerini CDN'den yayınlama

Birçok uygulama, ilk sayfa yüklemesinde tüm kullanıcılara aynı içeriği sunar. Örneğin, bir haber sitesi en son haberleri gösterebilir veya bir e-ticaret sitesi gösterilebilir en çok satan öğeleri içerir.

Bu içerik Cloud Firestore'dan sunuluyorsa her kullanıcı yeni bir sorgu gönderir. Çünkü bunlar sonuçlar kullanıcılar arasında önbelleğe alınmaz, uygulama daha yavaş ve daha pahalıya mal olabilir.

Çözüm: Paketler

Cloud Firestore paketleri, ortak sorgudan veri paketleri oluşturmanıza olanak tanır arka uçta gösterilen sonuçları alıp bu sonuçları CDN'de önbelleğe alınmış önceden hesaplanmış blob'lar. Bu sayede, kullanıcılarınıza daha hızlı ilk yükleme deneyimi sunar ve Cloud Firestore sorgu maliyetlerinizi azaltır.

Bu kılavuzda Cloud Functions'ı kullanarak paket ve Paket içeriğini dinamik olarak önbelleğe alıp yayınlamak için Firebase Hosting. Daha fazla Paketlerle ilgili bilgileri kılavuzlarda bulabilirsiniz.

Öncelikle son 50 "hikayeyi" sorgulamak için basit bir herkese açık HTTP işlevi oluşturun ve sonucu bir paket olarak sunar.

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()));
  }
}
      

Ardından Firebase Hosting'i, bu Cloud Functions işlevini aşağıdaki şekilde sunmak ve önbelleğe alacak şekilde yapılandırın: firebase.json değiştiriliyor. Bu yapılandırmayla Firebase Barındırma CDN'si Google Etiket Yöneticisi tarafından belirlenen önbellek ayarlarına göre Cloud Functions işlevi görür. Önbelleğin süresi dolduğunda aşağıdaki komutlar tetiklenir ve fonksiyonunu tekrar kontrol edin.

firebase.json
{
  "hosting": {
    // ...
    "rewrites": [{
      "source": "/createBundle",
      "function": "createBundle"
    }]
  },
  // ...
}

Son olarak web uygulamanızda, gruplandırılmış içeriği CDN'den alın ve yükleyin bunu Firestore SDK'ya aktarmanızı sağlar.

// 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
  // ...
}

Tahmini Tasarruf Miktarı

Günde 100.000 kullanıcıya ulaşan ve her kullanıcının ilk yüklemede, en çok okunan 50 haberi görmeye başlarsınız. Herhangi bir önbelleğe alma olmadan, Cloud Firestore'dan günde 50 x 100.000 = 5.000.000 belge okuma

Şimdi sitenin yukarıdaki tekniği kullandığını ve bu 50 sonucu önceden önbelleğe aldığını en fazla 5 dakika sürer. Yani her kullanıcı için sorgu sonuçlarını yüklemek yerine sonuçları saatte tam olarak 12 kez yüklenir. Kaç kullanıcı gelirse gelsin Cloud Firestore'a gönderilen sorguların sayısı aynı kalıyor. Şunun yerine: 5.000.000 belge okuma, bu sayfa 12 x 24 x 50 = 14.400 belge kullanır okuma sayısı. Firebase Hosting ve Cloud Functions, Cloud Firestore'daki maliyet tasarrufları sayesinde kolayca dengelenir.

Maliyet tasarrufları geliştiriciye fayda sağlasa da en büyük fayda sağlayan taraf; gösterir. Bu 50 dokümanı Firebase Hosting CDN'den yüklemek yerine doğrudan Cloud Firestore üzerinden 100-200 ms veya daha fazla yükleme süresini ölçer. Araştırmalar, hızlı sayfaların hızlı daha mutlu kullanıcılar demektir.