Incorporating Firebase JavaScript Modular Web Version 9 SDK into my Vue 3 / TypeScript application.
My understanding is that when utilizing real-time listeners with offline persistence in Firestore, the process should proceed as follows:
- Upon initialization of the listener, the callback triggers with data fetched from the local cache, followed by an immediate fetch from the server to ensure synchronization between the local cache and server data. If the server data matches the local cache, the callback should only trigger once with the data from the local cache.
- Upon any changes in the data, the callback fires with the updated information fetched directly from the server, which in turn updates the local cache accordingly.
- If there are no changes in the data, subsequent calls to the listener will initiate callbacks with data retrieved solely from the local cache.
However, despite setting up offline persistence, creating a listener for my Firestore data, and monitoring the data read sources...
I noticed an initial read from the local cache (as expected), followed by an unexpected second read from the server. Subsequent reads also continue to come from the server, rather than the local cache as anticipated.
Throughout this testing phase, no alterations were made to the data. Therefore, I expected all data reads triggered by the callback listener to originate from the local cache, not the server.
Oddly enough, the lone instance where a read did come from the local cache was during the initial setup of the listener, which aligns with expectations.
What might be causing this issue?
P.S. To simulate those "subsequent calls", I navigate to a different page within my SPA and then return to the component's page to prompt the behavior again.
src/composables/database.ts
export const useLoadWebsite = () => {
const q = query(
collection(db, 'websites'),
where('userId', '==', 'NoLTI3rDlrZtzWCbsZpPVtPgzOE3')
);
const firestoreWebsite = ref<DocumentData>();
onSnapshot(q, { includeMetadataChanges: true }, (querySnapshot) => {
const source = querySnapshot.metadata.fromCache ? 'local cache' : 'server';
console.log('Data came from ' + source);
const colArray: DocumentData[] = [];
querySnapshot.docs.forEach((doc) => {
colArray.push({ ...doc.data(), id: doc.id });
});
firestoreWebsite.value = colArray[0];
});
return firestoreWebsite;
};
src/components/websiteUrl.vue
<template>
<div v-if="website?.url">{{ website.url }}</div>
</template>
<script setup lang="ts">
import { useLoadWebsite } from '../composables/database';
const website = useLoadWebsite();
</script>