Angular 11 Firebase 服务器端渲染无限加载/挂起

3

我有一个 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服务器挂起,并且客户端看到一个'pending'查询永远不会完成,或者达到超时并部分呈现页面(即没有该查询结果的情况下)。

我正在使用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"]
1个回答

2

经过漫长的调试,我把问题源头锁定在了提问中列出的Firebase查询上。下面的查询是一个解决方法,可以让页面正常渲染,而不会卡住。

this.firestore.collection<T>('collection', ref => ref.limit(5))
    .valueChanges()   <<<<
    .pipe(
      take(2),        <<<<
    );

一方面,使调试变得困难的原因是以下更为合理的版本,它关闭源可观察对象会导致服务器也挂起(请记住,我不想观察更改,因此take(1)是有意义的)。然而,take(2)不会挂起... 这看起来像是堆栈中的某个 bug,很可能是 Firebase 中的问题。
这将是更为合理的解决方法... 但会导致 express 服务器挂起,使客户端处于pending请求状态。
this.firestore.collection<T>('collection', ref => ref.limit(5))
    .valueChanges()
    .pipe(
      take(1),      <<<<
    );

使用 Promise 也会导致卡顿,所以我目前只能采用 valueChanges() + take(2) 的解决方法。


1
花了很长时间,但这解决了我的问题!找到 take(1) 是如此困难。 - Zizazorro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接