-
-
Save zwily/e9e97e0f9f523a72c24c7df01d889482 to your computer and use it in GitHub Desktop.
/* | |
expo-firestore-persistence-hack | |
A fragile weaving of various modules together to convince the Firestore | |
web SDK to use persistence in an un-ejected Expo app. | |
To use, first: | |
``` | |
$ expo install expo-sqlite | |
$ yarn add indexeddbshim | |
``` | |
Then add the contents of this file to `expo-firestore-persistence-hack.js` | |
in your project, and import it very early (likely in App.js). After this is | |
imported, you can ask firestore to enable persistence: | |
`firebase.firestore().enablePersistence()` | |
The bulk of the work is done by indexeddbshim, which provides an IndexedDB | |
implementation on top of WebSQL. See the comments below above each hunk of | |
code to understand how hacky this all is. | |
*/ | |
import { SQLite } from "expo-sqlite"; | |
// Hack 1: The SQLite module from Expo is nominally | |
// WebSQL compatible. Let's just have the IndexedDB shim | |
// use it! | |
window.openDatabase = SQLite.openDatabase; | |
// Hack 2: indexeddbshim will try to examine navigator.userAgent | |
// if navigator exists. In React Native, it does, but has no | |
// userAgent set. Set one here to avoid a crash. | |
navigator.userAgent = "React-Native"; | |
// Hack 3: Initialize indexeddbshim with origin checks disabled, | |
// cause they'll fail on our platform (and don't quite make sense.) | |
// (Do not change this to an import, cause that will get hoisted above | |
// our userAgent hack above.) | |
const setGlobalVars = require("./node_modules/indexeddbshim/dist/indexeddbshim-noninvasive"); | |
setGlobalVars(window, { checkOrigin: false }); | |
// Hack 4: Firestore persistence really wants to use localStorage | |
// to communicate between tabs. We don't really care about | |
// communicating between tabs - everything will be in the same | |
// process. However, Firestore needs something. So we'll give it | |
// a really weak, fake, in-memory localStorage. (Persisted storage | |
// will go through IndexedDB and into SQLite, on disk.) | |
window.__localStorageStore = {}; | |
window.localStorage = { | |
getItem: function(key) { | |
return window.__localStorageStore[key]; | |
}, | |
setItem: function(key, value) { | |
window.__localStorageStore[key] = value; | |
}, | |
removeItem: function(key) { | |
delete window.__localStorageStore[key]; | |
}, | |
clear: function() { | |
window.__localStorageStore = {}; | |
}, | |
key: function(i) { | |
// Ever since ES6, the order of keys returned here is | |
// stable 🤞 | |
Object.keys(window.__localStorageStore)[i]; | |
} | |
}; | |
// You should now be able to initialize Firebase, and call | |
// firebase.firestore().enablePersistence() | |
// | |
// YMMV! YOLO! |
6.6.0
, the latest.
@nnatter would you mind posting the full example with your change? I notice you changed it to an import, but the original "Hack #3" says not do hoist it before the userAgent is set.
The code posted above should be a full example - is there anything missing for you?
Oh, sorry about that, got it! Trying it out now.
I haven't tested on collection queries yet, but I just did tests on Android and iOS for Firestore documents, and it seems to be working!
Hello, I have been using expo-firestore-offline-persistence
for about a month and it has been great. I ran into an issue after I accidentally installed the latest version of firebase
with npm install firebase
instead of expo install firebase
have been getting the following error:
Error enabling offline persistence. Falling back to persistence disabled: FirebaseError: [code=failed-precondition]: A newer version of the Firestore SDK was previously used and so the persisted data is not compatible with the version of the SDK you are now using. The SDK will operate with persistence disabled. If you need persistence, please re-upgrade to a newer version of the SDK or else clear the persisted IndexedDB data for your app to start fresh.
I tried deleting my node_modules
and reinstalling everything the correct way but am still getting the error. I don't know enough about SQLite or indexeddbshim and was hoping someone might be able to point me in the right direction for how to: or else clear the persisted IndexedDB data for your app to start fresh.
Hey there. This is really cool! Thanks for the great work on this :D
I'm currently using it to build out a prototype of an app, and I was wondering how far I could take it. I personally haven't found any issues with it so far, but my testing hasn't been too substantial. Do we know roughly what the guarantees are on this? Has anyone else been using it extensively?
I really like it; am I mad for thinking about using this in production/release?
Is there any way to use Indexed DB Polyfill in React Native Expo?
I'm getting this error
WARN [2022-11-14T20:48:04.371Z] @firebase/app: Firebase: Error thrown when reading from IndexedDB. Original error: undefined is not a function (near '...(0, _idb.openDB)...'). (app/idb-get).
WARN [2022-11-14T20:48:04.402Z] @firebase/app: Firebase: Error thrown when reading from IndexedDB. Original error: undefined is not a function (near '...(0, _idb.openDB)...'). (app/idb-get).
WARN [2022-11-14T20:48:04.415Z] @firebase/app: Firebase: Error thrown when writing to IndexedDB. Original error: undefined is not a function (near '...(0, _idb.openDB)...'). (app/idb-set).
At this point, I recommend using an Expo dev client with React Native Firebase.
Hello everyone, now 2023 but I still need this gist or this lib https://github.com/nandorojo/expo-firestore-offline-persistence to make firebase js lib have persistence. Because I'm still using Expo Go and firebase js to develop React Native app
But I can't install indexeddbshim
Both the latest version or 6.6.0 require node lib
error /Users/minhdrminh/Projects/ExpoTree/node_modules/sqlite3: Command failed.
Exit code: 1
Command: node-pre-gyp install --fallback-to-build
How can I fix it? any idea?
Thanks for your help
Btw, which version of indexeddbshim should I be using?