Search code examples
angularfirebasegoogle-cloud-firestorecachingpersistence

Can't read data from cache in Angular Firestore with persistence enabled after reload


I have a project with Angular 15 (15.2.0) and Angular Fire 7.5.0 (Firebase 9), that looks like this:

AppModule
| LoginModule  (lazy-loaded) with guard: canActivate(() => redirectLoggedInTo(['']))
| HomeModule   (lazy-loaded) with guard: canActivate(() => redirectUnauthorizedTo(['/login']))

I'm using this code in the AppModule to provide Firestore and enable persistence:

    provideFirestore(() => {
      console.log('providing from AppModule');
      const firestore = initializeFirestore(getApp(), {
        ignoreUndefinedProperties: true,
        cacheSizeBytes: CACHE_SIZE_UNLIMITED
      });
      enableIndexedDbPersistence(firestore).then(() => console.log('provided')).catch((err) => {
        if (err.code == 'failed-precondition') {
          console.error('Multiple tabs open, persistence can only be enabled in one tab at a a time.')
        } else if (err.code == 'unimplemented') {
          console.error('The current browser does not support all of the features required to enable persistence');
        }
      });
      return firestore;
    }),

When the app is loaded the first time, both console messages in provideFirestore are printed. I login and then in HomeModule I can read data. First time, there's nothing in cache, so it reads from the server. Subsequent calls fetch data successfully from cache.

This is how I'm reading data:

    const q = query(
      collection(getFirestore(), 'myCollection'),
      where('_userId', '==', getAuth().currentUser?.uid),
      orderBy('id', 'asc')
    );

    // I use this to read from cache
    getDocsFromCache(q);

    // If the querySnapshot is empty, I read from server
    getDocsFromServer(q);

The problem is when I reload the page. The "providing" console messages from AppModule won't print. Every call will fetch data from the server, getDocsFromCache will never return documents.

I inspected the IndexedDB and the data from when I first loaded the app is still there, but it can't be read, and new data won't be stored.

If I manually logout and log back in, I get data from cache again, so I think the issue is related to Angular, but I can't figure it out. Where could be the problem?


Solution

  • The solution is to move enableIndexedDbPersistence to the AppModule constructor:

    export class AppModule {
      constructor(firestore: Firestore) {
        enableIndexedDbPersistence(firestore).catch((err) => {
          if (err.code == 'failed-precondition') {
            console.error('Multiple tabs open, persistence can only be enabled in one tab at a a time.')
          } else if (err.code == 'unimplemented') {
            console.error('The current browser does not support all of the features required to enable persistence');
          }
        });
      }
    }
    

    Can't know for sure why the original code is not working, though it was in another project with Angular 13. Maybe some libraries were loaded at different times.