我如何将 Firebase 加载时间从 5 秒降低到低于 100 毫秒

发布: (2026年3月26日 GMT+8 19:22)
4 分钟阅读
原文: Dev.to

Source: Dev.to

问题

当 Muslifie 推出时,旅游列表页面的加载时间为 2–5 秒。在巴基斯坦、埃及和印度尼西亚等网络较慢的地区,用户在数据出现之前就已经离开了。

罪魁祸首是什么?每次用户打开应用时,Firebase 都会执行全新的 Firestore 查询——没有缓存,没有批处理,只是每次打开都进行原始读取。
在 200 多个导游档案并且还在增长的情况下,这既昂贵又慢。

我最初的直觉是使用 Flutter 内置的 Firestore 持久化进行客户端缓存。它稍有帮助,但:

  • 首次加载仍然很慢
  • 重新安装后数据会变陈旧
  • 无法控制缓存失效

对于导游每日可用性会变化的市场来说,这还不够。

解决方案

将繁重的工作转移到 Firebase Cloud Functions 并使用内存缓存。

// functions/index.js
let cachedData = null;
let cacheTime = null;
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

exports.getTours = functions.https.onCall(async (data, context) => {
  const now = Date.now();

  // Return cache if still fresh
  if (cachedData && (now - cacheTime)  ({ id: doc.id, ...doc.data() }));
  cacheTime = now;

  return cachedData;
});

关键洞察: Cloud Function 实例在调用之间保持温热,因此只要实例存活(通常为 15–30 分钟),缓存就会驻留在内存中。

冷启动后第一次调用函数的用户需要等待约 400 毫秒。随后每个用户都能在 100 毫秒以下 获得缓存数据。

指标

指标之前之后
首次加载2–5 秒100 毫秒以下
每日 Firestore 读取次数40,000+~800
Firebase 费用快速上升持平

感知性能

性能提升只有在用户在第一次冷启动期间不盯着空白屏幕时才有效。我配合 Flutter 骨架加载器 使用:

// lib/widgets/tour_list.dart
Widget build(BuildContext context) {
  return FutureBuilder>(
    future: fetchTours(),
    builder: (context, snapshot) {
      if (!snapshot.hasData) {
        return TourSkeletonList(); // Show skeleton while loading
      }
      return TourList(tours: snapshot.data!);
    },
  );
}

感知性能与实际性能同等重要。如果用户能看到一些正在进行的内容,他们会容忍加载过程。

未来改进

如果今天重新构建 Muslifie,我会加入:

  • 通过 Firebase Extensions 使用 Redis 缓存,实现多实例缓存共享
  • 增量加载 —— 首先即时显示前 10 条旅游,其余在后台加载
  • 应用启动时预取 —— 在用户甚至未导航之前就开始获取数据

收获

  • 不要过早优化;先进行性能分析。
  • 瓶颈并不是 Flutter 小部件或网络速度,而是多余的 Firestore 读取。
  • 一个只有 20 行的缓存函数就能显著降低读取次数和成本。
  • 为每次数据获取添加日志,观察时间到底花在了哪里;答案往往比想象的更简单。

最初发布于 buildzn.com.

0 浏览
Back to Blog

相关文章

阅读更多 »