Estoy tratando de escribir algunas operaciones de Firestore en un paquete separado para que pueda importarse y reutilizarse en diferentes aplicaciones web. Estoy creando un monorepo con diferentes paquetes y estoy tratando de usar Firebase v9 para el siguiente ejemplo:
Desde packageA A, estoy definiendo y exportando una getPosts(db) que toma un objeto Firestore y devuelve algunas publicaciones de la base de datos dada
// in 'packageA' import { collection, getDocs, Firestore } from 'firebase/firestore'; export const getPosts = async (db: Firestore) => { console.log('Passed in db: ', db); // This correctly prints the passed in Firestore object try { const postsCollection = collection(db, 'posts'); // This function will throw const querySnapshot = await getDocs(postsCollection); return querySnapshot.docs.map((doc) => doc.data()); } catch (e) { console.error('Error reading posts: ', e); } }En una aplicación web, estoy inicializando la aplicación Firebase y exportando la instancia de Firestore
// firebase.js in 'web-app-1' import { initializeApp } from 'firebase/app'; import { getFirestore } from 'firebase/firestore'; const firebaseConfig = { /* my Firebase config */ }; export const app = initializeApp(firebaseConfig); export const db = getFirestore(app); Luego estoy tratando de usar la función getPosts del paquete en un componente...
// App.js in 'web-app-1' import { db } from './firebase.js'; import { getPosts } from 'packageA'; let posts; async function loadPosts() { try { posts = await getPosts(db); } catch (e) { console.error(e); } } loadPosts(); // throws an error pero recibo el siguiente error de la llamada de collection(db, 'posts')
Error al leer las publicaciones: se esperaba que el primer argumento de la colección () fuera una CollectionReference, una DocumentReference o FirebaseFirestore
aunque la base de datos pasada se imprima correctamente en la consola (forma la función getPosts )
Nota: si copio toda la función getPosts y la uso directamente en la aplicación web (es decir, sin importarla de otro paquete), entonces funciona y obtiene correctamente las publicaciones.
Parece un error con la versión 9, y el método intenta usar una base de datos en tiempo real de Firebase en lugar de Firestore, por lo que el método envía un error para las colecciones.
Parece anular el hecho de que es Firestore cuando se usa la función, por lo que enviaría esto directamente al soporte de Firebase porque la forma en que se forma el paquete parece ser el problema principal.
He estado buscando un poco más y encontré esta respuesta a una pregunta similar para resolver mi problema también.
Básicamente, lo que tenía que hacer era especificar Firebase como una dependencia de peerDependency en el packageA A y no incluirlo en el paquete final . Las aplicaciones web que consumen el packageA A incluirán Firebase como una dependency regular.
Entonces, los archivos package.json ven de la siguiente manera
En el paquete de utilidades
{ "name": "packageA", "peerDependencies": { "firebase": "^9.6.3" } }y luego en las aplicaciones web
{ "name": "web-app-1", "dependencies": { "firebase": "^9.6.3", } }Este enfoque también tiene sentido para mi caso de uso, ya que la aplicación web (y solo la aplicación web) que inicializa la aplicación Firebase la incluirá en su paquete. Sin embargo, puedo imaginar que en algunos otros casos de uso esta no es una solución posible.
Sin embargo, he enviado mi problema al soporte de Firebase como se sugirió y aquí está su respuesta:
Hemos recibido algunos casos similares y ya estamos trabajando para solucionarlo. Sin embargo, puede llevar un tiempo debido a la carga de trabajo del equipo de ingeniería, tenga paciencia.
Actualmente estoy experimentando el mismo problema. La solución es importar los archivos directamente a través del paquete.
Tenga en cuenta que esto no es óptimo porque tengo que instalar los paquetes en el proyecto nativo nuevamente, por lo que requiere un poco de mantenimiento manual.
Esto garantiza que mi aplicación use la instancia de firebase y el paquete que está dentro de native/node_modules/
`
const { getDefaultConfig } = require("@expo/metro-config"); const path = require("path"); const projectRoot = __dirname; const workspaceRoot = path.resolve(__dirname, "../.."); const config = getDefaultConfig(__dirname); const extraNodeModules = { '@aim/utils': path.resolve(__dirname + '/../../packages/utils'), }; const watchFolders = [ path.resolve(__dirname + '/../../packages/utils') ]; config.watchFolders = [workspaceRoot]; config.resolver.nodeModulesPath = [ path.resolve(projectRoot, "node_modules"), path.resolve(workspaceRoot, "node_modules"), ]; module.exports = { transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: false, }, }), }, resolver: { extraNodeModules: new Proxy(extraNodeModules, { get: (target, name) => //redirects dependencies referenced from common/ to local node_modules name in target ? target[name] : path.join(process.cwd(), `node_modules/${name}`), }), }, watchFolders, }; // module.exports = config;`
tsconfig.json `
{ "compilerOptions": { "allowSyntheticDefaultImports": true, "jsx": "react-native", "lib": ["dom", "esnext"], "moduleResolution": "node", "noEmit": true, "skipLibCheck": true, "resolveJsonModule": true, "strict": true, "baseUrl": ".", "paths": { "@aim/utils/*": ["../../packages/utils/*"] } }, }`