简体   繁体   中英

Enable offline persistence Cloud Firestore

I would like to enable offline persistence using the Cloud Firestore Javascript SDK. I have structured my app in such as way that am storing firestore as property due to SSR.

import firebase from "firebase/app";

export class GetFirebase {
private firestore: firebase.firestore.Firestore;
private firebaseApp: firebase.app.App;
private firebaseConfig = {} // has the config from firebase

 private constructor() {
  this.firebaseApp = firebase.initializeApp(this.firebaseConfig);
  this.firestore = firebase.firestore();
 }
}

If I attempt to use the enablePersistence() method I get a void.

  this.firestore = firebase.firestore().enablePersistence();

I also cannot do this

  this.firestore = firebase.firestore();
  this.firestore.enablePersistence() // error cannot change settings after firestore is initialized.

I was looking for a Typescript or Javascript equivalent of the .. cascade operator from Dart and was not able to find it.

For the latest version (v9), the following works for me:

import {
  connectFirestoreEmulator,
  enableIndexedDbPersistence,
  getFirestore,
} from 'firebase/firestore';

export const getInitializedFirestore = () => {
  const firestore = getFirestore();

  // only enable emulator if in dev mode, and we haven't already enabled it
  if (
    process.env.NODE_ENV === 'development' &&
    (firestore as any)._getSettings().host === 'firestore.googleapis.com'
  ) {
    connectFirestoreEmulator(getFirestore(), '127.0.0.1', 8080);
    console.log('Firestore emulator attached!');
  }

  // only enable indexeddb if the firestore client hasn't been fully initialized
  if (!(firestore as any)._firestoreClient) {
    enableIndexedDbPersistence(firestore)
      .then(() => console.log('Persistence enabled!'))
      .catch((err) => console.error(err.message));
  }
  return firestore;
};

Replace any calls to getFirestore() with this getInitializedFirestore() function.

This is also HMR and page refresh safe, so dev mode is pleasant and doesn't throw errors. It can also safely be deployed to production without having to touch anything.

Basically, the Firebase SDK hides the properties needed to tell if the emulator/persistence has been enabled. This just abuses the type system a bit so we can access them.

There are many reasons than can cause the persistence call to return void:

  1. Incompatible version with offline data, there are certain services which are unimplemented for this feature which is the case of Node.js I made a replica of your case and I came up with the notice that it is not compatible with Node.js so it is important to verify if is compatible you server firebase enable offline . Also can cause error if you have multiple tabs open, persistence can only be enabled in one tab at a time. The current browser does not support all the resources required to enable persistence. For the web, offline persistence is supported only by the Chrome, Safari, and Firefox web browsers.

  2. You are making an asynchronous call and this happens because you are making a promise so the first time that you print the value result is void because the response has not arrived yet. However when the promise receives the information it won't be void any more. To more information about how works promises, promise documentation .

  3. You are not handling the promise and it can cause an issue. I made a replication and it caused the following warning: UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejection a promise which was not handled with.catch() firebase enable offline .


    firebase.firestore().enablePersistence()
      .catch((err) => {
          if (err.code == 'failed-precondition') {
              // Multiple tabs open, persistence can only be enabled
              // in one tab at a a time.
              // ...
          } else if (err.code == 'unimplemented') {
              // The current browser does not support all of the
              // features required to enable persistence
              // ...
          }
      });
    // Subsequent queries will use persistence, if it was enabled successfully

  1. You are using server side rendering so it could cause a mistaked to repair this you must use process.browser as the example process browser . I use this feature with nextjs, node and vue and it works.
    if (process.browser) {
      console.log('this code will only run on the browser')
    }

Cascade Operator I recommend you to open another thread to check this case because it is another topic in order that more people can find this. However, I found a blog where explain how to translate the cascade operator to JavaScript. There is not an equivalent but there are ways to do the same.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM