angular - Angular 11 Firebase 服务器端渲染无限加载/挂起
问题描述
我有一个 Angular 11 应用程序可以正常工作,即在非 SSR 模式下。这是一个查询 T 类型文档集合的示例(获取一次,不观察更改)。
在非 SSR 中工作的版本,查询集合的预期代码:
this.firestore.collection<T>('collection', ref => ref.limit(5))
.get()
.pipe(
map((qs: firebase.firestore.QuerySnapshot) => qs.empty ? [] : qs.docs.map(d => d.data() as T)),
);
当切换到 SSR 时,上面的代码会导致 express 服务器挂起,并且客户端会看到一个永远不会完成的“待处理”查询,或者遇到超时并导致页面部分呈现(即没有该查询的结果)。
我将 Angular 11 与 Ivy 一起使用。我的 package.json 中的相关条目:
{
"dependencies": {
"@angular/cdk": "^11.0.3",
"@angular/common": "~11.0.5",
"@angular/compiler": "~11.0.5",
"@angular/core": "~11.0.5",
"@angular/fire": "6.1.4",
"@angular/flex-layout": "^11.0.0-beta.33",
"@angular/forms": "~11.0.5",
"@angular/material": "^11.0.3",
"@angular/platform-browser": "~11.0.5",
"@angular/platform-browser-dynamic": "~11.0.5",
"@angular/platform-server": "~11.0.5",
"@angular/router": "~11.0.5",
"@nguniversal/express-engine": "^11.0.1",
"bootstrap": "^4.5.2",
"express": "^4.17.1",
"firebase": "^8.2.1",
"rxjs": "~6.6.3",
"tslib": "^2.0.0",
"zone.js": "~0.10.3"
},
"devDependencies": {
"@angular-builders/custom-webpack": "^11.0.0-beta.4",
"@angular-devkit/architect": "~0.1100.5",
"@angular-devkit/build-angular": "~0.1100.5",
"@angular/cli": "~11.0.5",
"@angular/compiler-cli": "~11.0.5",
"@nguniversal/builders": "^11.0.1",
"@ngx-builders/analyze": "^2.0.0",
"@types/express": "^4.17.0",
"@types/node": "^12.11.1",
"bufferutil": "^4.0.2",
"firebase-tools": "^9.0.1",
"ts-node": "~9.1.1",
"typescript": "~4.0.5",
"utf-8-validate": "^5.0.3",
"ws": "^7.4.1",
"xhr2": "^0.2.0"
}
}
在 angular.json 的 server.options 字段中,我必须添加以下内容以减轻以下错误ENOENT: no such file or directory, open '.../dist/server/src/protos/google/firestore/v1/firestore.proto'
externalDependencies: [
"@firebase/analytics",
"@firebase/analytics-types",
"@firebase/app",
"@firebase/app-types",
"@firebase/auth",
"@firebase/auth-interop-types",
"@firebase/auth-types",
"@firebase/component",
"@firebase/database",
"@firebase/database-types",
"@firebase/firestore",
"@firebase/firestore-types",
"@firebase/functions",
"@firebase/functions-types",
"@firebase/installations",
"@firebase/installations-types",
"@firebase/logger",
"@firebase/messaging",
"@firebase/messaging-types",
"@firebase/performance",
"@firebase/performance-types",
"@firebase/polyfill",
"@firebase/remote-config",
"@firebase/remote-config-types",
"@firebase/storage",
"@firebase/storage-types",
"@firebase/util",
"@firebase/webchannel-wrapper"]
解决方案
经过很长时间的调试会话后,我将问题的根源缩小到问题中列出的 Firebase 查询。以下查询是一种解决方法,可以在不挂起的情况下呈现页面。
this.firestore.collection<T>('collection', ref => ref.limit(5))
.valueChanges() <<<<
.pipe(
take(2), <<<<
);
难以调试的一个方面是因为下面更健全的版本,它关闭了源 observable 导致服务器也挂起(记住,我不想观察变化,所以take(1)是有意义的) . 但是, Take(2)并没有挂起……这看起来像是堆栈中某处的错误,可能在 Firebase 中。
这将是更明智的解决方法......但会导致快速服务器挂起,给客户端留下一个pending
请求:
this.firestore.collection<T>('collection', ref => ref.limit(5))
.valueChanges()
.pipe(
take(1), <<<<
);
使用 Promise 也会导致挂起,所以我目前只剩下 valueChanges()+take(2) 解决方法。
推荐阅读
- sql - 如何存储来自 SELECT 语句的数据并使用该数据与 UPDATE 语句循环
- java - 从另一个类调用 actionlistener 或以某种方式对放置在一个按钮上的多个 actionlistener 进行排序?
- scala - groupby scala 字符串列表
- javascript - 使用 php、javascript 和 ajax 进行简单登录
- java - 使用 CriteriaQuery 选择通用主键
- c++ - 使用 C++ 导出注册表
- sqlite - GDX-SQLite android.database.CursorIndexOutOfBoundsException:请求索引 -1,大小为 1
- java - 如何使用带有jpa的spring boot一起软删除父母和孩子(级联)
- php - 未从数据库中获取数据
- debugging - oc debug pod 使用最新图像而不是调试过的原始图像