Sajikan konten Firestore yang dibundel dari CDN

Banyak aplikasi menyajikan konten yang sama untuk semua pengguna pada pemuatan halaman pertama. Misalnya situs berita mungkin menampilkan berita terbaru, atau situs e-niaga mungkin menampilkan item terlaris.

Jika konten ini disajikan dari Cloud Firestore, setiap pengguna akan mengeluarkan kueri baru untuk hasil yang sama saat mereka memuat aplikasi. Karena hasil ini tidak di-cache antar pengguna, aplikasi menjadi lebih lambat dan lebih mahal dari yang seharusnya.

Solusi: Bundel

Bundel Cloud Firestore memungkinkan Anda untuk merakit bundel data dari hasil kueri umum di backend menggunakan Firebase Admin SDK, dan menyajikan blob yang telah dihitung sebelumnya ini dalam cache di CDN. Ini memberi pengguna Anda pengalaman memuat pertama yang jauh lebih cepat dan mengurangi biaya kueri Cloud Firestore Anda.

Dalam panduan ini, kita akan menggunakan Cloud Functions untuk membuat bundel dan Firebase Hosting untuk menyimpan dan menyajikan konten bundel secara dinamis. Informasi lebih lanjut tentang bundel tersedia di panduan .

Pertama, buat fungsi HTTP publik sederhana untuk menanyakan 50 "cerita" terbaru dan menyajikan hasilnya sebagai bundel.

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

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

Selanjutnya konfigurasikan Firebase Hosting untuk melayani dan meng-cache Cloud Function ini dengan memodifikasi firebase.json . Dengan konfigurasi ini, CDN Firebase Hosting akan menyajikan konten bundel sesuai dengan pengaturan cache yang ditetapkan oleh Cloud Function. Ketika cache kedaluwarsa, itu akan menyegarkan konten dengan memicu fungsi lagi.

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

Terakhir di aplikasi web Anda, ambil konten yang dibundel dari CDN dan muat ke 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
  // ...
}

Perkiraan Penghematan

Pertimbangkan situs web berita yang mendapatkan 100.000 pengguna per hari dan setiap pengguna memuat 50 berita utama yang sama pada pemuatan awal. Tanpa caching apa pun, ini akan menghasilkan 50 x 100.000 = 5.000.000 dokumen yang dibaca per hari dari Cloud Firestore.

Sekarang asumsikan situs mengadopsi teknik di atas dan menyimpan 50 hasil tersebut hingga 5 menit. Jadi, alih-alih memuat hasil kueri untuk setiap pengguna, hasilnya dimuat tepat 12 kali per jam. Tidak peduli berapa banyak pengguna yang tiba di situs, jumlah kueri ke Cloud Firestore tetap sama. Alih-alih 5.000.000 pembacaan dokumen, halaman ini akan menggunakan 12 x 24 x 50 = 14.400 pembacaan dokumen per hari. Biaya tambahan yang kecil untuk Firebase Hosting dan Cloud Functions dengan mudah diimbangi dengan penghematan biaya Cloud Firestore.

Sementara pengembang mendapat manfaat dari penghematan biaya, penerima manfaat terbesar adalah pengguna. Memuat 50 dokumen ini dari CDN Firebase Hosting, bukan dari Cloud Firestore secara langsung, dapat dengan mudah memangkas 100-200 md atau lebih dari waktu muat konten halaman. Penelitian telah berulang kali menunjukkan bahwa halaman yang cepat berarti pengguna yang lebih bahagia.