欢迎参加我们将于 2022 年 10 月 18 日举办的 Firebase 峰会(线上线下同时进行),了解 Firebase 如何帮助您加快应用开发速度、满怀信心地发布应用并在之后需要时轻松地扩大应用规模。立即报名

Bir CDN'den paketlenmiş Firestore içeriği sunun

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 en çok satan ürünleri gösterebilir.

Bu içerik Cloud Firestore'dan sunuluyorsa, her kullanıcı uygulamayı yüklediğinde aynı sonuçlar için yeni bir sorgu gönderir. Bu sonuçlar kullanıcılar arasında önbelleğe alınmadığından, uygulama olması gerekenden daha yavaş ve pahalıdır.

Çözüm: Paketler

Cloud Firestore paketleri, Firebase Admin SDK'sını kullanarak arka uçta yaygın sorgu sonuçlarından veri paketleri oluşturmanıza ve bir CDN'de önbelleğe alınmış bu önceden hesaplanmış blobları sunmanıza olanak tanır. Bu, kullanıcılarınıza çok daha hızlı bir ilk yükleme deneyimi sağlar ve Cloud Firestore sorgu maliyetlerinizi azaltır.

Bu kılavuzda, paketler oluşturmak için Bulut İşlevlerini ve paket içeriğini dinamik olarak önbelleğe almak ve sunmak için Firebase Hosting'i kullanacağız. Paketler hakkında daha fazla bilgi kılavuzlarda mevcuttur.

Önce en son 50 "hikayeyi" sorgulamak ve sonucu bir paket olarak sunmak için basit bir genel HTTP işlevi oluşturun.

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.json öğesini değiştirerek bu Bulut İşlevini sunmak ve önbelleğe almak için firebase.json . Bu yapılandırmayla, Firebase Barındırma CDN'si, paket içeriğini Bulut İşlevi tarafından belirlenen önbellek ayarlarına göre sunacaktır. Önbelleğin süresi dolduğunda, işlevi yeniden tetikleyerek içeriği yenileyecektir.

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

Son olarak web uygulamanızda, paketlenmiş içeriği CDN'den alın ve Firestore SDK'ya yükleyin.

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

Günde 100.000 kullanıcıya ulaşan ve her kullanıcı ilk yüklemede aynı 50 en iyi haberi yükleyen bir haber sitesi düşünün. Önbelleğe alma olmadan bu, Cloud Firestore'dan günde 50 x 100.000 = 5.000.000 belge okumasıyla sonuçlanır.

Şimdi sitenin yukarıdaki tekniği benimsediğini ve bu 50 sonucu 5 dakikaya kadar önbelleğe aldığını varsayalım. Böylece her kullanıcı için sorgu sonuçlarını yüklemek yerine, sonuçlar saatte tam olarak 12 kez yüklenir. Siteye kaç kullanıcı ulaşırsa ulaşsın, Cloud Firestore'a yapılan sorgu sayısı aynı kalır. 5.000.000 belge okuması yerine, bu sayfa günde 12 x 24 x 50 = 14.400 belge okuması kullanır. Firebase Hosting ve Cloud Functions için küçük ek maliyetler, Cloud Firestore maliyet tasarruflarıyla kolayca dengelenir.

Geliştirici maliyet tasarrufundan yararlanırken, en büyük yararlanan kullanıcıdır. Bu 50 belgeyi doğrudan Cloud Firestore yerine Firebase Barındırma CDN'sinden yüklemek, sayfanın içerik yükleme süresinden 100-200 ms veya daha fazlasını kolayca tıraş edebilir. Araştırmalar, hızlı sayfaların daha mutlu kullanıcılar anlamına geldiğini defalarca göstermiştir.