Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 11 Firebase Server-side rendering infinite loading / pending

I have an angular 11 app that works great normally, i.e. in non-SSR mode. Here is a sample querying a collection of documents, of type T (get once, not observing the changes).

Version that works in non-SSR, the expected code to query the collection once:

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)),
    );

When switching to SSR, the above code leads to the express server hanging, and the client see a 'pending' query that never completes, or hits a timeout and leaves the page partially rendered (i.e. without the results of that query).

I am using Angular 11 with Ivy. The relevant entries in my 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"
  }
}

In angular.json, in the server.options field, I had to add the following to mitigate the following error 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"]
like image 810
Julien Avatar asked Mar 11 '26 07:03

Julien


1 Answers

After a very long debugging session, I narrowed down source of the problem to Firebase query listed in the question. The following query is a workaround that gets the page rendered, without hanging.

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

One aspect that made it hard to debug was because the more sane version here below, which closes the source observable causes the server to also hang (Remember, I do not want to observe the changes, so take(1) is what makes sense). Take(2) however, does not hang... This looks like a bug somewhere in the stack, likely in Firebase.

This would be the more sane workaround... but causes the express server to hang, leaving the client with a pending request:

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

Using promises also causes hanging, so I'm currently left with the valueChanges()+take(2) workaround.

like image 93
Julien Avatar answered Mar 13 '26 03:03

Julien



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!