محتوای Firestore همراه را از CDN ارائه دهید

بسیاری از برنامه ها محتوای یکسانی را در بارگذاری صفحه اول به همه کاربران ارائه می دهند. به عنوان مثال یک سایت خبری ممکن است آخرین داستان ها را نشان دهد، یا یک سایت تجارت الکترونیک ممکن است موارد پرفروش را نشان دهد.

اگر این محتوا از Cloud Firestore ارائه شود، هر کاربر هنگام بارگذاری برنامه، درخواست جدیدی برای نتایج مشابه صادر می کند. از آنجایی که این نتایج بین کاربران ذخیره نمی‌شوند، برنامه کندتر و گران‌تر از آن چیزی است که باید باشد.

راه حل: بسته نرم افزاری

بسته‌های Cloud Firestore به شما این امکان را می‌دهند که بسته‌های داده را از نتایج جستجوی رایج در پشتیبان با استفاده از Firebase Admin SDK جمع‌آوری کنید و این حباب‌های از پیش محاسبه‌شده را در حافظه پنهان در یک CDN ارائه دهید. این به کاربران شما تجربه بارگیری اولیه بسیار سریع‌تری را می‌دهد و هزینه‌های جستجوی Cloud Firestore شما را کاهش می‌دهد.

در این راهنما از توابع ابری برای تولید بسته‌ها و میزبانی Firebase برای ذخیره‌سازی پویا و ارائه محتوای بسته استفاده می‌کنیم. اطلاعات بیشتر در مورد بسته ها در راهنماها موجود است.

ابتدا یک تابع HTTP عمومی ساده ایجاد کنید تا 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);
});
      
جاوا

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 Hosting را پیکربندی کنید تا با تغییر firebase.json ، این تابع Cloud را ارائه و ذخیره کند. با این پیکربندی، Firebase Hosting CDN محتوای بسته را مطابق تنظیمات حافظه پنهان تنظیم شده توسط Cloud Function ارائه می کند. هنگامی که حافظه پنهان منقضی شود، با فعال کردن مجدد تابع، محتوا را تازه می کند.

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

پس انداز تخمینی

یک وب سایت خبری را در نظر بگیرید که روزانه 100000 کاربر دریافت می کند و هر کاربر همان 50 خبر برتر را در بارگذاری اولیه بارگذاری می کند. بدون هیچ گونه ذخیره سازی، این امر منجر به 50 x 100000 = 5000000 خواندن سند در روز از Cloud Firestore می شود.

حال فرض کنید سایت تکنیک بالا را اتخاذ کرده و آن 50 نتیجه را حداکثر تا 5 دقیقه در حافظه پنهان نگه می دارد. بنابراین به جای بارگیری نتایج پرس و جو برای هر کاربر، نتایج دقیقاً 12 بار در ساعت بارگذاری می شوند. مهم نیست که چند کاربر به سایت وارد می شوند، تعداد پرس و جوها به Cloud Firestore ثابت می ماند. به جای 5,000,000 خواندن سند، این صفحه از 12 x 24 x 50 = 14,400 خواندن سند در روز استفاده می کند. هزینه های اضافی کوچک برای میزبانی Firebase و توابع Cloud به راحتی با صرفه جویی در هزینه Cloud Firestore جبران می شود.

در حالی که توسعه دهنده از صرفه جویی در هزینه سود می برد، بزرگترین ذینفع، کاربر است. بارگیری این 50 سند از CDN میزبانی Firebase به جای مستقیماً از Cloud Firestore می تواند به راحتی 100-200 میلی ثانیه یا بیشتر از زمان بارگذاری محتوای صفحه را حذف کند. مطالعات بارها نشان داده اند که صفحات سریع به معنای کاربران شادتر است.