You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Angular/Fire17+Ionic7.6.2的Firestore全离线功能

Angular/Firestore 离线功能与无限缓存配置指南

一、核心配置:启用Firestore持久化缓存

要开启Firestore的离线持久化和无限缓存,需在provideFirestore中完成以下配置:

  • 设置缓存大小为CACHE_SIZE_UNLIMITED,取消数据缓存上限
  • 启用持久化存储,支持多标签页同步离线数据
  • 开启持久化缓存索引自动创建,避免离线时索引缺失导致的加载失败

修改provideFirestore的配置代码:

importProvidersFrom(provideFirestore(() => {
  const firestore = getFirestore();
  // 设置无限缓存大小
  firestore.settings({
    cacheSizeBytes: CACHE_SIZE_UNLIMITED
  });
  // 启用持久化存储,处理多标签页同步
  firestore.enablePersistence({
    synchronizeTabs: true
  }).catch(err => {
    if (err.code === 'failed-precondition') {
      console.error('Firestore持久化失败:多标签页冲突,请关闭其他标签页');
    } else if (err.code === 'unimplemented') {
      console.error('当前浏览器不支持Firestore持久化功能');
    }
  });
  // 自动创建持久化缓存索引
  enablePersistentCacheIndexAutoCreation(firestore);
  return firestore;
})),

二、解决离线启动数据加载卡顿问题

应用启动无网络时卡顿,是因为Firestore默认等待网络连接初始化索引。需在应用初始化阶段先完成持久化初始化,再加载数据:

  1. 补全APP_INITIALIZER的工厂函数逻辑,确保先初始化持久化:
async function initializeMyApp(authService: AuthService, firestoreDataService: FirestoreDataService, firestore: Firestore) {
  return async () => {
    try {
      // 先初始化Firestore持久化,失败时不中断应用启动
      await firestore.enablePersistence({ synchronizeTabs: true }).catch(err => {
        console.warn('Firestore持久化初始化警告:', err);
      });
      // 执行自定义初始化逻辑(如加载用户数据)
      await authService.initAuth();
      await firestoreDataService.loadInitialData();
    } catch (err) {
      console.error('应用初始化失败:', err);
    }
  };
}
  1. 确保APP_INITIALIZER配置中使用上述工厂函数(替换原空函数)。

三、确保离线修改持久化

Firestore原生API默认支持离线修改持久化,只需注意以下两点:

  • 数据操作使用Firestore原生方法(addDoc/setDoc/updateDoc),不要绕开这些API,离线时修改会自动保存到本地,网络恢复后自动同步
  • 使用实时监听方法获取数据,而非单次get()请求:
    在FirestoreDataService中用snapshotChanges()替代get(),离线时自动读取缓存:
    getItems() {
      return this.firestore.collection('items').snapshotChanges();
    }
    
    若必须使用get(),需指定从缓存读取:
    async getItemOffline(id: string) {
      const docRef = doc(this.firestore, 'items', id);
      const snapshot = await getDoc(docRef, { source: 'cache' });
      return snapshot.data();
    }
    

完整修改后的main.ts代码

import { APP_INITIALIZER, enableProdMode, importProvidersFrom } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { RouteReuseStrategy, provideRouter } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';

import { routes } from './app/app.routes';
import { AppComponent } from './app/app.component';
import { environment } from './environments/environment';
import { IonicStorageModule } from '@ionic/storage-angular';
import { Drivers } from '@ionic/storage';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { getAuth, provideAuth } from '@angular/fire/auth';
import { getAnalytics, provideAnalytics, ScreenTrackingService, UserTrackingService } from '@angular/fire/analytics';
import { getFirestore, provideFirestore, CACHE_SIZE_UNLIMITED, enablePersistentCacheIndexAutoCreation, Firestore } from '@angular/fire/firestore';
import { FirestoreDataService } from './app/firestoredata.service';
import { AuthService } from './app/services/auth.service';

if (environment.production) {
  enableProdMode();
}

async function initializeMyApp(authService: AuthService, firestoreDataService: FirestoreDataService, firestore: Firestore) {
  return async () => {
    try {
      // 初始化Firestore持久化
      await firestore.enablePersistence({ synchronizeTabs: true }).catch(err => {
        console.warn('Firestore持久化初始化警告:', err);
      });
      // 执行自定义初始化逻辑
      await authService.initAuth();
      await firestoreDataService.loadInitialData();
    } catch (err) {
      console.error('应用初始化失败:', err);
    }
  };
}

bootstrapApplication(AppComponent, {
  providers: [
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    importProvidersFrom(
      IonicModule.forRoot({}),
      IonicStorageModule.forRoot({
        driverOrder: [Drivers.IndexedDB, Drivers.LocalStorage],
      }),
    ),
    provideRouter(routes),
    importProvidersFrom(HttpClientModule),
    importProvidersFrom(TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: createTranslateLoader,
        deps: [HttpClient]
      }
    })),
    importProvidersFrom(provideFirebaseApp(() => initializeApp(environment.firebaseConfig))),
    importProvidersFrom(provideAuth(() => getAuth())),
    importProvidersFrom(provideAnalytics(() => getAnalytics())),
    // 配置Firestore离线缓存与持久化
    importProvidersFrom(provideFirestore(() => {
      const firestore = getFirestore();
      // 设置无限缓存大小
      firestore.settings({
        cacheSizeBytes: CACHE_SIZE_UNLIMITED
      });
      // 启用持久化,处理多标签页同步
      firestore.enablePersistence({
        synchronizeTabs: true
      }).catch(err => {
        if (err.code === 'failed-precondition') {
          console.error('Firestore持久化失败:多标签页冲突,请关闭其他标签页');
        } else if (err.code === 'unimplemented') {
          console.error('当前浏览器不支持Firestore持久化功能');
        }
      });
      // 启用持久化缓存索引自动创建
      enablePersistentCacheIndexAutoCreation(firestore);
      return firestore;
    })),
    ScreenTrackingService, UserTrackingService,
    {
      provide: APP_INITIALIZER,
      useFactory: initializeMyApp,
      multi: true,
      deps: [AuthService, FirestoreDataService, Firestore]
    }
  ],
});

export function createTranslateLoader(http: HttpClient) {
  return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

内容的提问来源于stack exchange,提问作者user880625

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 09:06:01