You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义npm包无法复用主应用Firestore对象读取数据库的问题及解决

自定义npm包复用主应用Firestore实例的SDK冲突解决方法

问题场景与错误表现

我正在开发基于Firestore的自定义npm包,想直接传入主应用已初始化好的Firestore对象来实例化包内的类:

import { firestoreTest } from 'my-package'

const app = initializeApp(firebaseConfig)
const db = getFirestore(app)
const test = new firestoreTest(db)

调用await test.getDoc('pathto/doc')时触发错误:

Uncaught (in promise) FirebaseError: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore

尝试多种初始化方式后,只有在包内用firebaseConfig完整初始化Firebase应用才能读取数据,但无法继承主应用的认证上下文,只能访问公开集合。如果直接传入主应用的DocumentReference到包中,会出现:

Uncaught (in promise) FirebaseError: Type does not match the expected instance. Did you pass a reference from a different Firestore SDK?

主应用和包使用同版本Firebase,且已将Firebase设为peer dependency,预期能无缝复用主应用的Firebase对象。包内测试代码如下:

export class firestoreTest {
  private db: Firestore
  private app: FirebaseApp
  private dbFromApp: Firestore
  private localApp: FirebaseApp
  private localDb: Firestore

  constructor(firebaseConfig: FirebaseOptions, app: FirebaseApp, db: Firestore) {
    this.db = db
    this.app = app

    this.dbFromApp = getFirestore(app)

    this.localApp = initializeApp(firebaseConfig)
    this.localDb = getFirestore(this.localApp)
  }

  public async getDoc(docPath: string, ref?: DocumentReference<DocumentData, DocumentData>) {
    /* 能读取但无认证上下文,仅访问公开集合 */
    // const data = await getDoc(doc(this.localDb, docPath).withConverter(converter<any>()))

    /* 触发参数类型错误 */
    // const data = await getDoc(doc(this.dbFromApp, docPath).withConverter(converter<any>()))

    /* 触发参数类型错误 */
    const data = await getDoc(doc(this.db, docPath).withConverter(converter<any>()))

    /* 触发SDK实例不匹配错误 */
    // const data = ref && (await getDoc(ref.withConverter(converter<any>())))

    console.log(data?.data())
  }
}

核心原因分析

问题出在开发阶段本地依赖加载的重复实例:即使把Firebase设为peer dependency,用npm link或本地源安装包时,主应用和包会各自加载一份独立的Firestore SDK。Firebase内部的类型校验会严格检查实例来源,不同SDK实例生成的对象无法互通,从而触发各种类型错误。

生产环境推送到GitHub后安装正常,是因为此时包会复用主应用的Firebase依赖,不会重复加载SDK实例。

解决方案

1. 开发阶段用relative-deps解决依赖重复问题

relative-deps可以让本地开发的npm包直接复用主应用的依赖,避免重复加载SDK:

  • 在自定义包的package.json中配置relative-deps,指向主应用的node_modules或具体Firebase依赖
  • 安装并配置后,包会直接使用主应用的Firestore SDK实例,类型校验和认证上下文继承都能正常工作。

2. 确保peer dependency配置正确

在包的package.json中明确Firebase相关依赖为peer dependency,避免生产环境重复安装:

"peerDependencies": {
  "firebase": "^9.0.0" // 匹配主应用使用的版本
},
"devDependencies": {
  "firebase": "^9.0.0" // 仅开发时用于类型校验
}

3. 简化包内初始化逻辑

包内不需要重新初始化Firebase应用,直接使用主应用传入的Firestore实例即可,去掉不必要的本地初始化代码:

export class firestoreTest {
  private db: Firestore

  constructor(db: Firestore) {
    this.db = db // 直接使用主应用传入的实例
  }

  public async getDoc(docPath: string) {
    const docRef = doc(this.db, docPath).withConverter(converter<any>())
    const data = await getDoc(docRef)
    console.log(data?.data())
  }
}

内容的提问来源于stack exchange,提问作者KristapsR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 07:27:42