我对Firebase不是很有经验,最近我一直在用Next.js + Firebase做一些事情,偶然发现了这行必要的代码:
const app = !getApps().length ? initializeApp(config) : getApp()
据我所知,这可以防止创建多个配置相同的Firebase应用程序。但是,首先,这是从哪里来的?其次,getApps是如何函数知道所有其他非DEFAULT的应用程序吗?它的返回值是可变的还是只读的?它如何getApp()函数(最后没有“s”)甚至知道哪个应用程序是我默认返回的,我不向它传递任何东西...
我找不到任何关于这一点,也没有在Firebase的文档,也没有从他们的主要发言人,如大卫东,托德Kerpelman,弗兰克货车普费伦。我知道,Firebase的文档是字面上最糟糕的星球上,马里奥游戏“要好得多,但即使这样...
帮助:)
2条答案
按热度按时间1mrurvl11#
在Firebase SDK中有这样的内容:
Firebase JS SDK采用TypeScript编写。
在你的代码中,你不需要
const app = ...
,只是滥用所有的Firebase函数。函数getFirestore()
会给你一个你需要使用的Firebase示例,与getApp()
相同。您可以使用enableIndexedDbPersistence(getFirebase())
,这样您就可以在客户端浏览器中本地缓存数据,而不需要任何Redux/Pinia/Vuex解决方案。如果您使用onSnapshot()
侦听器,这将减少数据库查询。或者将getDocFromCache()
与getDoc()
结合使用。好吧,如果你忘记了OOP是如何工作的,并且开始用函数式/结构化编程来思考,那么它是如何工作的就开始变得显而易见了。你的应用程序是封装的,但是你有一个"getter""setter"来处理它。比OOP更好,更容易理解。没有任何设计模式需要学习。而且库可以很容易地被编译器/捆绑器树摇动,所以它是轻量级的。
jqjz2hbq2#
在@Mises的answer的基础上,我可以提供一些附加的上下文。
作为帮助开发人员避免错误和竞争条件的内置保护的一部分,如果为同一应用程序名调用两次,
initializeApp()
将抛出错误(这里没有给出名称,而是使用"[DEFAULT]"
)。这样设计的另一个原因是,抛出一个错误更容易,而不是将传入每个initializeApp()
调用的配置对象与前一个进行比较。由于这种行为,initializeApp()
应该在应用程序中只被调用一次,或者在当前文件的顶部,或者在某个中央依赖项中(例如app.js
),然后当需要它时,可以使用getApp()
、getFirestore()
等将其引入当前文件。getApp()
和getApps()
函数是Firebase SDK功能的一部分,您可以在一个应用程序中使用多个项目。此处记录了此功能的使用。加载Firebase依赖关系
对于一些开发者来说,Firebase是相当严重的依赖(特别是对于遗留的JavaScript SDK)。所以他们不想不必要地加载它是可以理解的。这对于基于Web的应用程序来说尤其重要,因为交互时间很重要,或者当试图优化Firebase的云函数的冷启动时间以获得最佳响应时间时。
在这个由@doug-stevenson制作的关于optimizing cold-start times的旧视频中,Doug介绍了如何使用布尔标志来指示Firebase Admin SDK是否已初始化。这允许不使用Admin SDK的函数跳过加载,并更快地返回结果。
一些开发人员不喜欢在全局范围内乱放这样的标志,所以他们寻找一种即时的替代方法,即在遗留JavaScript SDK中检查
firebase.apps
的长度,在Admin SDK中检查admin.apps
的长度。同样的方法也适用于客户端JavaScript SDK:
对于单个项目的应用程序,这很快就成为了检查默认应用程序是否初始化的事实标准,导致以下代码行出现在所有地方(特别是在使用每个文件一个组件的框架时):
或
总结/ TL:DR;
随着
"firebase"
和"firebase-admin"
向模块化Firebase JavaScript SDK的迁移,使用遗留代码的开发人员和新手正在通过遵循modular SDK migration guide来更新它。这将导致以下遗留代码:
被一一翻译成现代的代码
此行的主要目的是获取
FirebaseApp
类的正确初始化示例而不引发错误,您可以将其传递给SDK(如Analytics和Cloud Firestore)中包含的Firebase服务的入口点函数。引擎盖下的一瞥
要了解如何在SDK中的服务之间处理默认应用程序示例,您可以查看源代码。与
FirebaseApp
相关的函数的实现类似于以下代码。**注意:**为了简洁起见,我省略了一些验证并重命名了一些变量,您应该查看full source或API reference以了解详细信息。
SDK中提供的每个服务都有一个入口点函数。在传统的命名空间SDK中,它采用
firebase.firestore()
的形式,而现代的模块化SDK则使用getFirestore()
。每个入口点函数都遵循类似的策略,看起来类似于以下代码。**注意:**和以前一样,这是一个简化的版本。详细信息请参见完整的源代码和API参考。