Test Repo here, simply clone it, npm install, and npm run dev:ssr
https://github.com/tskweres/angularfire-ssr-test
** make sure to input your own firebaseConfig in the environments
In the app.component.ts, you'll see that I inject AngularFireStore, and then make a query on a collection.
The query completes and the console logs the result, but when launching the browser in chrome, the web page never renders.
If I do not make the this.db.collection('.....') call, the web page renders.
Any ideas?
It's almost as if AngularFire makes the query call, but it doesn't fire next() or some sort of interceptor issue? Ultimately the html doesn't get rendered to Chrome, but there's no error
That sounds like a Zone.js issue. Note your on RC, give 6.0.0 final a shot. In the meantime I'll look at your repo, looping back to wrapping 6.0.1 shortly in which I'm aiming to button up a lot of these issues.
@jamesdaniels Cool I appreciate it. I've tried with 6.0.0.rc-2 and 6.0.0, same issue. You can check the repo, but here's my package.json:
{
"name": "universal-starter-v9",
"version": "0.1.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/angular/universal-starter.git"
},
"contributors": [
"AngularClass <[email protected]>",
"PatrickJS <[email protected]>",
"Jeff Whelpley <[email protected]>",
"Jeff Cross <[email protected]>",
"Mark Pieszak <[email protected]>",
"Jason Jean <[email protected]>",
"Fabian Wiles <[email protected]>",
"Kamil Mysliwiec <[email protected]>",
"Michael Prentice <[email protected]>"
],
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"dev:ssr": "ng run universal-starter-v9:serve-ssr",
"serve:ssr": "node dist/universal-starter-v9/server/main.js",
"prebuild:ssr": "ngcc",
"build:ssr": "ng build --prod && ng run universal-starter-v9:server:production",
"prerender": "ng run universal-starter-v9:prerender"
},
"pre-commit": [],
"private": true,
"dependencies": {
"@angular/animations": "~9.0.0",
"@angular/common": "~9.0.0",
"@angular/compiler": "~9.0.0",
"@angular/core": "~9.0.0",
"@angular/fire": "^6.0.0",
"@angular/forms": "~9.0.0",
"@angular/platform-browser": "~9.0.0",
"@angular/platform-browser-dynamic": "~9.0.0",
"@angular/platform-server": "~9.0.0",
"@angular/router": "~9.0.0",
"@nestjs/common": "^6.11.6",
"@nestjs/core": "^6.11.6",
"@nestjs/ng-universal": "^3.0.0",
"@nestjs/platform-express": "^6.11.6",
"@nguniversal/common": "9.0.0",
"@nguniversal/express-engine": "9.0.0",
"class-transformer": "^0.2.3",
"class-validator": "^0.9.1",
"classlist.js": "1.1.20150312",
"core-js": "^2.6.5",
"firebase": "^7.13.1",
"rxjs": "~6.5.2",
"terser": "^4.1.2",
"tsconfig-paths": "^3.8.0",
"tslib": "^1.10.0",
"zone.js": "~0.9.1"
},
"devDependencies": {
"@angular-devkit/architect": "<0.900 || ^0.900.0-0 || ^9.0.0-0",
"@angular-devkit/build-angular": "~0.900.1",
"@angular/cli": "~9.0.1",
"@angular/compiler-cli": "~9.0.0",
"@angular/language-service": "~9.0.0",
"@grpc/proto-loader": "^0.5.4",
"@nguniversal/builders": "^9.0.0",
"@types/jasmine": "~3.5.3",
"@types/jasminewd2": "~2.0.8",
"@types/node": "~13.7.0",
"codelyzer": "^5.2.1",
"cpy-cli": "2.0.0",
"express": "4.17.1",
"firebase-tools": "^7.12.1",
"fuzzy": "^0.1.3",
"http-server": "0.12.1",
"inquirer": "^6.2.2",
"inquirer-autocomplete-prompt": "^1.0.1",
"jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.4.1",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~2.1.1",
"karma-jasmine": "~3.1.0",
"karma-jasmine-html-reporter": "^1.5.2",
"mini-css-extract-plugin": "^0.9.0",
"nodemon": "^2.0.2",
"pre-commit": "1.2.2",
"protractor": "~5.4.3",
"reflect-metadata": "0.1.13",
"ts-loader": "^6.2.1",
"ts-node": "~8.6.2",
"tslint": "~6.0.0",
"typescript": ">=3.6.4 <3.8.0",
"wait-on": "^4.0.0",
"webpack-cli": "^3.3.6",
"ws": "^7.2.3",
"xhr2": "^0.2.0"
}
}
Angular.json:
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"universal-starter-v9": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/universal-starter-v9/browser",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "universal-starter-v9:build"
},
"configurations": {
"production": {
"browserTarget": "universal-starter-v9:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "universal-starter-v9:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "universal-starter-v9:serve"
},
"configurations": {
"production": {
"devServerTarget": "universal-starter-v9:serve:production"
}
}
},
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/universal-starter-v9/server",
"main": "server.ts",
"tsConfig": "tsconfig.server.json",
"externalDependencies": [
"@nestjs/microservices",
"@nestjs/microservices/microservices-module",
"@nestjs/websockets",
"@nestjs/websockets/socket-module",
"cache-manager",
"@firebase/firestore",
"firebase/firestore",
"@grpc/proto-loader"
]
},
"configurations": {
"production": {
"outputHashing": "media",
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"sourceMap": false,
"optimization": false
}
}
},
"serve-ssr": {
"builder": "@nguniversal/builders:ssr-dev-server",
"options": {
"browserTarget": "universal-starter-v9:build",
"serverTarget": "universal-starter-v9:server"
},
"configurations": {
"production": {
"browserTarget": "universal-starter-v9:build:production",
"serverTarget": "universal-starter-v9:server:production"
}
}
},
"prerender": {
"builder": "@nguniversal/builders:prerender",
"options": {
"browserTarget": "universal-starter-v9:build:production",
"serverTarget": "universal-starter-v9:server:production",
"routes": [
"/"
]
},
"configurations": {
"production": {}
}
},
"deploy": {
"builder": "@angular/fire:deploy",
"options": {}
}
}
}
},
"defaultProject": "universal-starter-v9",
"cli": {
"analytics": false
}
}
I think my issue is related to this. #2416
Do you get timeout error?
I'm creating working repo with my problem from scratch now.
No timeout error, the chrome page still remains it its 'loading' state with the 'X' in the top left, but no server errors, no webpage render
@tskweres : Do you have a workaround right now? I have the same issue in my project and invested hours of debugging, but have no idea how to solve it. I'm not that familiar with zone.js.
Btw. I can reproduce this issue with Angular 8 and Angular Fire 5.4.2
Angular CLI: 8.3.25
Node: 10.19.0
OS: darwin x64
Angular: 8.2.13
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... platform-server, router
Package Version
--------------------------------------------------------------------
@angular-devkit/architect 0.802.2
@angular-devkit/build-angular 0.803.25
@angular-devkit/build-ng-packagr 0.802.2
@angular-devkit/build-optimizer 0.803.25
@angular-devkit/build-webpack 0.803.25
@angular-devkit/core 8.2.2
@angular-devkit/schematics 8.3.25
@angular/cdk 8.2.3
@angular/cli 8.3.25
@angular/fire 5.4.2
@angular/material 8.2.3
@ngtools/webpack 8.3.25
@nguniversal/express-engine 8.2.6
@nguniversal/module-map-ngfactory-loader 8.1.1
@schematics/angular 8.3.25
@schematics/update 0.803.25
ng-packagr 5.7.1
rxjs 6.5.3
typescript 3.5.3
webpack 4.39.2
I don't, waiting on 6.0.1 :(
Continuing to code running the app on the front-end until the fix is out
I've checked today. I also have infinity loading when call this.db.collection('.....'). I'll try to reproduce this issue with Angular 9. Will update soon
@tskweres, @n3nikita : Which versions of the Firebase SDK are you using? I just tried to downgrade to an older version, in my case from 7.14.1 to 7.0.0. And now it seems that the rendering is working.
Was only working on local SSR, not on Firebase Functions SSR. :(
@tskweres I've found that I face this problem when I trying to get only one item by id from the database.
Articles page
I get all my articles by several parameters. It loads well and I don't have any errors.
this.db.collection('articles', ref => ref.orderBy('date', 'desc')
.where('status', '==', status)
.startAfter(last.date)
.limit(count))
.valueChanges({ idField: 'id' }).subscribe(articles => {
this.updateSubjectByStatus(status, articles as Article[], isPush);
});
Article page
I'm trying to get only one article by Id. This method works before but after update to Angular 9 and adding SSR I get an infinity loading.
return this.db.doc('articles/' + id)
.snapshotChanges()
.pipe(
take(1),
map(doc => {
return {
id: doc.payload.id,
...(doc.payload.data() as object)
} as Article;
}));
I changed my method by the following one and page seems to be working fine. Infinity loading gone.
return this.db.collection('articles').doc(id).valueChanges();
I also use the AuthService at my component and when I subscribe to authState I face this problem.
My auth.service.ts file:
export class AuthService {
constructor(
private authFire: AngularFireAuth) {
}
isAuth() {
return this.authFire.authState;
}
}
This is how I call isAuth() at my component:
this.authService.isAuth().subscribe(data => {
this.user = data;
});
when I comment this code page loads well
@n3nikita @rogervanwile
FYI:
Same issue here, fixed by downgrading back to 5.2.3
@urish can you post your package.json?
I try running with @angular/fire 5.2.3, but it breaks AngularFireAuth, I'm assuming AngularFireAuth changed between 5.2.3 -> 6
Yes, you need to add .auth before any calls to signInWithPopup(), e.g.
this.afa.signInWithPopup(new firebase.auth.GoogleAuthProvider());
turns into
this.afa.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
and possibly other methods
@urish And what is the import at the top? Can I import AngularFireAuth?
Yes, it hasn't changed
@urish I appreciate the help here, still working through errors introduced by rolling back.
Any idea how to avoid this one?
Error: Uncaught (in promise): TypeError: app.firestore is not a function
Tried removing node_modules and package-lock.json and re-installing, still there though, must be a version of one of the other packages
I had to apply the following patch to fix this:
diff --git a/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/server.js b/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/server.js
index d1c0a61..e74af64 100644
--- a/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/server.js
+++ b/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/server.js
@@ -40,7 +40,7 @@ function getServerConfig(wco) {
node: false,
};
if (bundleDependencies) {
- config.externals = [...externalDependencies];
+ config.externals = [...externalDependencies, /^firebase/];
}
else {
config.externals = [
I tried Angularfire at 5.2.3 and applied the fix you mentioned, but the original error of no web page rendering still persists. Here's my package.json
{
"name": "testapp-web",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"dev:ssr": "ng run testapp-web:serve-ssr",
"serve:ssr": "node dist/testapp-web/server/main.js",
"build:ssr": "ng build --prod && ng run testapp-web:server:production",
"prerender": "ng run testapp-web:prerender"
},
"private": true,
"dependencies": {
"@angular/animations": "^9.0.7",
"@angular/common": "~9.1.2",
"@angular/compiler": "~9.1.2",
"@angular/core": "~9.1.2",
"@angular/fire": "5.2.3",
"@angular/forms": "~9.1.2",
"@angular/platform-browser": "~9.1.2",
"@angular/platform-browser-dynamic": "~9.1.2",
"@angular/platform-server": "~9.1.2",
"@angular/router": "~9.1.2",
"@grpc/proto-loader": "^0.5.4",
"@nguniversal/express-engine": "^9.0.2",
"@types/googlemaps": "^3.39.3",
"bulma": "^0.8.1",
"express": "^4.15.2",
"firebase": "^7.14.2",
"fsevents": "^2.1.2",
"lodash.throttle": "^4.1.1",
"ngx-google-places-autocomplete": "^2.0.4",
"ngx-toastr": "^12.0.0",
"rxjs": "~6.5.4",
"rxjs-compat": "^6.5.5",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/architect": "^0.900.0-0 || ^0.900.0",
"@angular-devkit/build-angular": "~0.901.2",
"@angular/cli": "~9.1.2",
"@angular/compiler-cli": "~9.1.2",
"@angular/language-service": "~9.1.2",
"@nguniversal/builders": "^9.0.2",
"@types/express": "^4.17.0",
"@types/jasmine": "~3.5.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"bufferutil": "^4.0.1",
"codelyzer": "^5.1.2",
"domino": "^2.1.4",
"firebase-tools": "^7.12.1",
"fuzzy": "^0.1.3",
"inquirer": "^6.2.2",
"inquirer-autocomplete-prompt": "^1.0.1",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~2.1.0",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.2",
"protractor": "~5.4.3",
"ts-node": "~8.3.0",
"tslint": "~5.18.0",
"typescript": "~3.7.5",
"utf-8-validate": "^5.0.2",
"ws": "^7.2.3",
"xhr2": "^0.2.0"
}
}
Just gonna stick with the latest of everything I suppose, hopefully 6.0.1 fixes it soon
I am facing the same issue here. I tried to keep console logs in my initial components to see if I can make out anything that breaks in between, but no use. I ran a simple universal application without angular fire and it works very fine. But this is causing an infinite loading issue. I am out of options. Below is my package.json in case anyone has any idea to resolve this.
"dependencies": {
"@agm/core": "^1.1.0",
"@agm/snazzy-info-window": "^1.1.0",
"@angular/animations": "~9.1.3",
"@angular/cdk": "^9.2.1",
"@angular/common": "~9.1.3",
"@angular/compiler": "~9.1.3",
"@angular/core": "~9.1.3",
"@angular/fire": "^6.0.0",
"@angular/forms": "~9.1.3",
"@angular/localize": "9.1.3",
"@angular/platform-browser": "~9.1.3",
"@angular/platform-browser-dynamic": "~9.1.3",
"@angular/platform-server": "~9.1.3",
"@angular/router": "~9.1.3",
"@ks89/angular-modal-gallery": "^7.3.0-rc.1",
"@ng-bootstrap/ng-bootstrap": "^6.1.0-beta.2",
"@nguniversal/express-engine": "^9.1.0",
"@nguniversal/module-map-ngfactory-loader": "9.0.0-next.9",
"angular-count-to": "0.0.3",
"angular-tilt": "^1.2.0",
"angular-typing-animation": "^0.5.4",
"animate-scss": "^3.2.1",
"animate.css": "^3.7.2",
"bootstrap": "^4.4.1",
"classlist.js": "^1.1.20150312",
"cookieconsent": "^3.1.1",
"core-js": "^3.6.5",
"express": "^4.17.1",
"firebase": "^7.14.2",
"firebaseui": "4.5.0",
"firebaseui-angular": "^4.1.0",
"jspdf": "^1.5.3",
"jspdf-autotable": "^3.4.4",
"lodash": "4.17.15",
"moment-timezone": "^0.5.28",
"mousetrap": "^1.6.5",
"ng-animate": "^0.3.4",
"ng2-animate-on-scroll": "^2.0.0",
"ng2-cookies": "^1.0.12",
"ng2-scroll-to-el": "^1.2.1",
"ng5-slider": "^1.2.4",
"ngx-build-plus": "^9.0.6",
"ngx-content-loading": "^0.1.3",
"ngx-cookieconsent": "^2.2.3",
"ngx-logger": "^4.1.9",
"ngx-masonry": "^9.1.1",
"ngx-masonry-gallery": "^3.0.0",
"ngx-owl-carousel-o": "^3.0.0",
"ngx-spinner": "^9.0.2",
"ngx-swiper-wrapper": "^9.0.1",
"ngx-toastr": "^12.0.1",
"razorpay": "^2.0.6",
"rxjs": "^6.5.5",
"rxjs-compat": "^6.5.5",
"snazzy-info-window": "^1.1.1",
"sweetalert2": "^9.10.12",
"tslib": "^1.11.1",
"web-animations-js": "^2.3.2",
"zone.js": "~0.10.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "0.901.3",
"@angular/cli": "^9.1.3",
"@angular/compiler-cli": "~9.1.3",
"@angular/language-service": "~9.1.3",
"@types/express-serve-static-core": "^4.17.5",
"@types/googlemaps": "^3.39.3",
"@types/jasmine": "~3.5.10",
"@types/jasminewd2": "~2.0.8",
"@types/lodash": "^4.14.150",
"@types/mousetrap": "^1.6.3",
"@types/node": "^13.13.2",
"bufferutil": "^4.0.1",
"codelyzer": "^5.2.2",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~5.0.2",
"karma": "~5.0.2",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~2.1.1",
"karma-jasmine": "~3.1.1",
"karma-jasmine-html-reporter": "^1.5.3",
"localstorage-polyfill": "^1.0.1",
"protractor": "~5.4.4",
"replace-in-file": "^5.0.2",
"serverless-webpack": "^5.3.1",
"ts-loader": "^7.0.1",
"ts-node": "~8.9.0",
"tslint": "~6.1.1",
"typescript": "^3.8.3",
"utf-8-validate": "^5.0.2",
"webpack-cli": "^4.0.0-beta.8",
"ws": "^7.2.3",
"xhr2": "^0.2.0"
}
@tskweres You can check my Angular 9 Universal + Firebase sample project angular-universal-firebase. It seems to be working with the following code:
return this.db.collection('articles').doc(id).valueChanges();
but there's still infinity loading when I try get an authState.
@tskweres You can check my Angular 9 Universal + Firebase sample project angular-universal-firebase. It seems to be working with the following code:
return this.db.collection('articles').doc(id).valueChanges();but there's still infinity loading when I try get an authState.
But honestly, do we need auth to work in server? I mean you just need to present it in client end right? My current solution which I am following is to check whether I am on server with isPlatformBrowser(plaformId) and then render auth functionality in client and skip it on server. That way it will come onto client and render it without the infinity loading.
But unfortunately, I had to skip all my db calls for now. Not sure what's wrong with the db calls.
I have below:
httpDataService.ts
getCategoryMenu(): Observable<MenuItems> {
return this.afs.collection('collection').doc<MenuItems>('menuitems').valueChanges();
}
Then in my component, I would do as below:
this.categories = this.httpDataService
.getCategoryMenu()
.pipe(takeUntil(this.subs$))
.map((res) => {
const menuData = res.items;
const itemShuffled = shuffle(menuData).splice(0, 6);
return itemShuffled.map((menu) => {
const menuArr = { title: '', category: '' };
menuArr.title = menu.name;
menuArr.category = kebabCase(menu.slug);
return menuArr;
});
});
In my case, I suspect that rxjs and lodash methods are not working in ssr. Any pointers anyone?
@jamesdaniels Definitely some crazy RxJS stuff going on. I found it works if:
"@angular/animations": "~9.0.0",
"@angular/common": "~9.0.0",
"@angular/compiler": "~9.0.0",
"@angular/core": "~9.0.0",
"@angular/fire": "^6.0.0-canary.9e19b14",
"@angular/forms": "~9.0.0",
"@angular/platform-browser": "~9.0.0",
"@angular/platform-browser-dynamic": "~9.0.0",
"@angular/platform-server": "~9.0.0",
"@angular/router": "~9.0.0",
Hope that helps!
@kshkrao3 Thank you for the solution. I call auth only at browser and infinity loading gone.
@n3nikita Tell me something, do you use rxjs operators on the firestore data and still it works, or you are just manipulating plain db documents to display in frontend?
@n3nikita Tell me something, do you use
rxjs operatorson the firestore data and still it works, or you are just manipulating plaindb documentsto display in frontend?
When I use the following code I get an infinity loading:
getById(id: string): Observable<Book> {
return this.db.doc('books/' + id)
.snapshotChanges()
.pipe(
take(1),
map(doc => {
return {
id: doc.payload.id,
...(doc.payload.data() as object)
} as Book;
}));
}
so I changed my code to the following:
getById(id: string): Observable<Book> {
return this.db.collection('books').doc<Book>(id).valueChanges();
}
I think the problem might be connected with rxjs operators.
Any update on this I cannot get the Firebase functions to deploy using Firestore. I have tried everything mentioned in this thread with no avail.
Pointless evening using Firebase if this doesn't work.
@tbacon1991 .. As for now, we are waiting for the v6.0.1 and hopefully it resolves these issues. Bdw, what's the error you are getting?
@kshkrao3 Hopefully comes soon pretty big piece to the puzzle, for now I have copied by database to local and will be making updates via local HTTP requests, any changes admin have have to come via me for the moment. Relatively small so not a huge issue but still flipping annoying.
My main error was/is:
Detailed stack trace: Error: Cannot find module '@firebase/app'
I have tried installing Firebase in the functions folder, providing it as an external dependency etc as mentioned in the thread. Tried all different versions but still getting the same error. If the full error is is needed I can try and dig it out.
Could you please paste your app package.json, angular.json and functions package.json? Let's see if you miss anything.
Might have found a fix for this, basically:


Would do a MR but unfortunately we're not yet on Angular 9. Did a small repository to try and replicate this with the realtime database the other day and also got Zone issues when forking out, e.g.
this.trips$ = this.db.list('/fav-ids').snapshotChanges().pipe(
switchMap(featured => combineLatest(
featured.map(id => this.db.object(`stories/${id.payload.exportVal()}`).snapshotChanges())
)),
With the fix it works, when stress testing I still get instabilities though when running multiple instances in parallel. This strangely happens for both, same process and also different node processes which is super weird. In production I now retry SSR by setting a timeout of 5s and if the render fails retrying. Not really optimal but I have no idea how to further debug this.
@tskweres I struggled with infinity loading problem all day. Now I tried to remove the pipe and everything works fine.
```ts
this._db.collection
.valueChanges()
// .pipe(first())
.subscribe((slides) => console.log('hi: ', slides));
I have not tried deploying yet, but it looks like a temporary solution to the problem.
"@angular/core": "9.1.4",
"@angular/fire": "6.0.0",
"firebase": "7.14.2",
```
@levonka gotcha, would be more interested to get a proper fix, I use pipes for lots of observable logic, thanks for the heads up!
I'm facing the same issue I need to pipe first() because I'm using a route resolver. removing the first() pipe works but breaks my application's logic
@davideast .. Any idea when angularfire 6.0.1 is going to release? We are stuck with this rxjs issue and this seems critical for now.. :)
Why do you think that version 6.0.1 is fixing that? For me it looks like no core developer is working on this issue, or do I miss something? Does someone know, how to get a higher priority to this bug?
I am also not sure if AngularFire is causing this issue, it could also be a bug in one of the dependencies.
I'll agree on this being critical.
After a lot of hours of debugging, infinite loaders and following every comment on this thread i just managed to get it to work.
I'm currently on:
'@angular/*' : 9.0.1
"@nguniversal/express-engine": 9.0.0
"firebase": "^7.14.4",
"rxjs": "^6.5.5",
"@angular/fire": "^6.0.0-canary.9e19b14",
Here the relative snippet of code that is causing trouble for me. It would appear that the problem has to do with subscribe
This causes infinite loader:
this.post$ = this.postsService.getPost(friendlyurl);
this.post$.subscribe(t =>{
this.title.setTitle(t.SeoTitle)
})
This works just fine:
this.post$ = this.postsService.getPost(friendlyurl).pipe(tap(t => this.title.setTitle(t.SeoTitle)));
and just for reference postsService.getPost is just:
return this.db.collection('posts').doc<post>(friendlyUrl).valueChanges();
I'll try bumping the version back to 9.1.7 and see what happens.
I hope this helps.
So you're saying removing all subscribes fixes the issue?
@jamesdaniels a new version coming soon?
So you're saying removing all subscribes fixes the issue?
@jamesdaniels a new version coming soon?
Yes, for my case at least. That did it. I've even deployed it and it works as expected
So you're saying removing all subscribes fixes the issue?
@jamesdaniels a new version coming soon?Yes, for my case at least. That did it. I've even deployed it and it works as expected
I agree that this could be the good solution. But what if we just want to subscribe to any changes in the db? kind of real-time. I think tap would not work then right?
So you're saying removing all subscribes fixes the issue?
@jamesdaniels a new version coming soon?Yes, for my case at least. That did it. I've even deployed it and it works as expected
I agree that this could be the good solution. But what if we just want to subscribe to any changes in the
db? kind of real-time. I thinktapwould not work then right?
If you separate you code into server and client side then you should be ok. When it's for SSR you just need to take the data once. After its on the client you can use subscribe normally.
Would love to see an update for this, it seems like writing separate subscriptions for serverside vs client defeats the purpose
Tracked it down further - it all does stem from AngularFireAuth not working server side.
However - would love to have this working, I'd like to render the homepage with the user's avatar in the header and not have it flash because it's waiting for client side, any ideas?
@tskweres you can store a cookie with a firebase custom auth token after login, use that in SSR to log a user in so that they get a version that is rendered for their auth state (@Inject(REQUEST) the request to read the cookie and use signInWithCustomToken).
In the end:
All works
Why was this closed? I think a .pipe(take(1)) still breaks, as is mentioned above. Without the pipe, it works fine.
Agreed, this thread seemed to have gotten a little sidetrack... simply try to generate a latest ng9 + AngularFire, try to use .pipe(take(1)) or .pipe(first()) and the page will never resolve. No AngulareFireAuth needed. It's really that easy to reproduce. I can push up a github sample repo if needed.
Reopened for those still having issues
@tskweres Then again, I don't want to hijack your thread if your original issue has already been resolved. I can open up a new one too.
In the end:
- Make sure any resolvers that return Observables complete
- Make sure any guards that return Observables complete
- AngulareFireAuth only works client side, so must check for platform
- Implement cookies for server side auth
All works
After some further testing it would appear this is still an incomplete solution. The solution i previously mentioned worked fine for
return this.db.collection('posts').doc<post>(friendlyUrl).valueChanges();
which returns a single item.
i tried something similar with
return this.db.collection<post>('posts', ref => ref.where('PublishDate', '<=', new Date()).orderBy('PublishDate', 'desc').limit(limit)).valueChanges();
which is a supposed to return a filtered array and i got infinite loading again.
In my attempt to resolve this i tried the AsyncApiCallHelperService by @alvarotf
which seems to help somewhat but it did confuse me more.
After wrapping my request with the AsyncApiCallHelperService the first request gets infinity loading and all subsequent requests work just fine. Let me clarify that i have no idea how AsyncApiCallHelperService works and can not really read it.
Edit:
On a personal note, since i have to deliver my project and it is already overdue because of this issue, my solution ended up being a .Net core wrapper app. When the angular app is in SSR the calls are not done directly to firestore but to my separate app.
I have been experiencing this issue as well with some interesting symptoms. First, I was getting infinity loading in some guards I wrote that were using AngularFireAuth to fetch the current user and check their credentials. I fixed this issue by replacing my handrolled auth guards with AngularFireAuthGuard.
Digging into the source, AngularFireAuthGuard does not depend on AngularFireAuth, but prepares its own authState in a way very similar to AngularFireAuth but without this keepUnstableUntilFirst pipe.
Here is the authState preparation for AngularFireAuth: https://github.com/angular/angularfire/blob/master/src/auth/auth.ts#L67
Here is the authState preparation for AngularFireAuthGuard: https://github.com/angular/angularfire/blob/master/src/auth-guard/auth-guard.ts#L43
Another symptom I've experience is a long hang when trying to load data from firestore in a resolver. Interestingly enough, I timed it and if you wait 60s, the hanging eventually stops and the SSR'd page is returned to the browser. This leads me to believe that what ever subscription is holding up the render (i.e. keeping it from becoming stable) is has some kind of timeout on it for firestore.
I haven't been able to prove it yet, but my gut feeling is that the subscription to the auth state that the firestore sdk creates in order to make authorized requests to the firestore server isn't completing properly, which is causing all of these issues.
I'd really like to see this issue fixed, as I am already deeply invested in firestore, and SSR is critical to the success of my business.
I've got a quick update after a lot of debugging across different versions of @angular/fire. I have discovered that this firestore hanging issue i described above (with the 60s timeout) was introduced in @angular/fire: 5.4.0. @angular/fire: 5.3.1 does not experience this hanging issue. I tested both versions using firebase: 7.15.1 which is the latest version.
Looking at the patch notes for 5.4.0, it sounds like there was an overhaul to how zones are used in this library which I think would be consistent with symptoms we are all seeing.
I'm going to try to dig into the commits between those two version to see if I can find the regression.
I rolled mine back to @angular/fire: 5.3.1 and it seemed to fix my issues using take(1) and first() as well. Nice work @jadengis!
I rolled mine back to @angular/fire: 5.3.1 and it seemed to fix my issues using
take(1)andfirst()as well. Nice work @jadengis!
My guard is still not working
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree
{
return this.angularFireAuth.user.pipe(
map(user => {
this.userService.user = user;
if (!user) {
this.userService.auth().then();
}
return !!user;
}),
);
}
I'm getting the exact same infinite loading issue as @jadengis described, with a 60 second timeout when using resolvers with SSR. And any angularfire observable using take(1). Interestingly if I open up a new localhost tab and refresh the page the original page will complete. Using Angular 10 and angularfire 6.0.1. Rolling back to 5.3.1 worked.
@odenman250 Do you have examples of importing Auth into the app.module, hard to find docs on 5.3.1, I want to try it as well.
My problem is suddenly back after working for a month, and SSR hangs
@tskweres, you might need to use providers in that version. Unfortunately I had go back to 6.0.2 because it cased other SSR issues. I have worked out that whenever you use .where() with .pipe(take(1)) it causes the infinite loading on version 6.0.2. You can use take() without a .where() query and visa versa.
I've noticed that compound queries break SSR as well.
This works:
this.db.collection('users').valueChanges().pipe(take(1)).toPromise();
This will make SSR hang:
const ref = this.db.collection('users', (ref) => {
let query: firebase.firestore.CollectionReference | firebase.firestore.Query = ref;
query = query.where('age', '==', age);
query = query.where('city', '==', age);
query = query.where('dob', '==', dob);
query = query.orderBy('createdAt', 'desc');
return query;
});
ref.valueChanges().pipe(take(1)).toPromise();
Same problem here. In my case, if I do the following it works:
private getCollection(ref: string, queryFn?: any, transferKey?: string): Observable<any[]> {
const keyGenerationString = `firebase:collection:${transferKey}`;
const collectionKey = makeStateKey<any>(keyGenerationString);
let exists: any;
if (this.isBrowser) {
exists = this.transferState.get(collectionKey, [] as any);
return of(exists);
} else {
return this.afStore.collection(ref, queryFn).snapshotChanges().pipe(
map(actions => {
return actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return { id, ...data as {} };
});
}),
tap(actions => {
if (!this.isBrowser) {
if (!actions) { return; }
this.transferState.set(collectionKey, actions);
}
})
);
}
}
But if I try to do the same for a single document, for some unknown reason, it hangs for ever.
So changing
this.afStore.collection(ref, queryFn).snapshotChanges().pipe(...
for
this.afStore.doc(ref).valueChanges().pipe(
makes the server side to not render the page.
I've checked with the debugger on the server side and it seems to be trapped in the following function in the internal/timers.js
function processTimers(now)
No clue if that's of any help for somebody with more knowledge.
In case someone is struggling with this, after a lot of testing, this two functions seem to work for me:
private getDocument(ref: string, transferKey?: string) {
const stateKeyString = `firebase:document:${transferKey}`;
const documentKey = makeStateKey<any>(stateKeyString);
let exists: any;
const docObservable = this.afStore.doc(ref).snapshotChanges().pipe(
map(snapshotChanges => {
return snapshotChanges.payload.data();
}),
tap(snapshotChanges => {
if (!this.isBrowser) {
if (!snapshotChanges) { return; }
this.transferState.set(documentKey, snapshotChanges);
}
})
);
if (this.isBrowser) {
exists = this.transferState.get(documentKey, undefined);
if (exists) {
docObservable.pipe(
startWith(exists)
);
}
}
return docObservable;
}
private getCollection(ref: string, queryFn?: any, transferKey?: string): Observable<any[]> {
const stateKeyString = `firebase:collection:${transferKey}`;
const collectionKey = makeStateKey<any>(stateKeyString);
const collectionObservable = this.afStore.collection(ref, queryFn).snapshotChanges().pipe(
map(snapshotChanges => {
return snapshotChanges.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return { id, ...data as {} };
});
}),
tap(snapshotChanges => {
if (!this.isBrowser) {
if (!snapshotChanges) { return; }
this.transferState.set(collectionKey, snapshotChanges);
}
})
);
let exists: any;
if (this.isBrowser) {
exists = this.transferState.get(collectionKey, undefined);
if (exists) {
collectionObservable.pipe(
startWith(exists)
)
}
}
return collectionObservable;
}
Any slight modification or addition of rxjs operators breaks them so be careful
Does anyone know if a fix is on the way for this?
Facing this issue as well. Somewhat racing against the clock now because firebase functions is removing support for node 8 soon. My app is in production with node 8, angular 7, and angularfire 5, which works great. Updating to node 10 created a cascading effect of needing to upgrade dependencies and here I am trying to make angular 9 SSR work.
I can confirm the same behavior @jadengis and others have described. First I made sure I was not using any afAuth serverside, which solved some issues. But I absolutely _need_ to make firestore queries serverside to get the SEO benefit, which require ref.where() and piping, so I still have the infinite (60s) loading problem.
@alan-agius4 @jamesdaniels I tell everyone how much I love Angularfire, I am known as the "firebase guy" at my company, but this issue is a showstopper... if you could please 馃檹 take some time to address this issue I'm sure many in the community would be very grateful. The comment above about zone changes back in 5.4.0 seems like a great starting point. Thank you!!
@inorganik I am currently using v5.3.1 with the nodejs 12 runtime in App Engine and this is working fine for me, so If you are in a pinch don't let upgrading to v6 hold you back from updating your runtime. I agree though that I really would like this issue fixed. This is a major blocker for anyone wanting to use v6 and universal together, and it has been open for months now.
@jadengis Are you using angular 9? In my angular 9 project, if I try to downgrade to 5.3.1, it builds and serves, but If I request a route that uses firestore from the server, it crashes and server throws this error:
TypeError: Object(...)(...).firestore is not a function
Looks like this issue still persists in version 6.0.3. Anyone else have any luck?
@inorganik Sorry I missed your question. I actually started experiencing this as well if I upgrade to firebase: 7.19. I'm not sure why though, I've stepped through the code and everything should be loading properly. It works with 7.17.
@jadengis Which version of angular?
@inorganik 10.1
@jamesdaniels Would it be possible for us to get an update on this issue? This bug has been in since February, and is making upgrading past @angular/fire v5.3.1 and firebase v7.17 impossible for anyone using Universal and Firestore together.
I'm not able to reproduce. I've have an SSR sample that's working fine, any help would be appreciated.
Okay, let me try to build a reproduction repo and I'll get back to you.
@jamesdaniels The sample SSR you are having includes any piece of code wherein you have added pipe, map operators something like mentioned in this comment?
https://github.com/angular/angularfire/issues/2420#issuecomment-620070301
Hey @jamesdaniels
I'm not able to reproduce. I have an SSR sample that's working fine, any help would be appreciated.
Is this sample public? Maybe we can take a look?
Thanks
I'm not able to reproduce. I've have an SSR sample that's working fine, any help would be appreciated.
Hey @jamesdaniels , I am definitely getting this issue as well when using ssr, angularfire 6.0.3, firebase 7.21.1 and angular cli 10.1.3. Any use of pipes will cause a hang.
I'm not able to reproduce. I've have an SSR sample that's working fine, any help would be appreciated.
Hey @jamesdaniels , I am definitely getting this issue as well when using ssr, angularfire 6.0.3, firebase 7.21.1 and angular cli 10.1.3. Any use of pipes will cause a hang.
@jamesdaniels , @jadengis, I've setup a simple repo to test firestore, ssr. Hangs when using a resolver and ssr. Works fine as a normal browser app. https://github.com/odenman250/angularfire-ssr-test
Como ustedes han probado, las libreria Angularfire rompe SSR, igual que FlexLayout y tantas otras.
He adoptado otro enfoque. Accedo a los datos que necesito para las vistas renderizadas( SSR) con un "resolve() sobre la ruta, que hace una consulta http a la API de Firestore. Es conveniente tener un par de directivas (una para incluir en los div para SSR, otra para los div sin SSR, que leen), las directivas usan isPlatformServer and isPlarformBroser para limpiar o crear el ViewContainer donde se declaren. El Localstore tampoco funciona, por lo que han de importar makeStateKey, TransferState para evitar llamadas repetidas a la base de datos.
@jamesdaniels Not to pester you too much, but @odenman250 provided a reproduction scenario of the hang we are experiencing in the new versions of angular/fire. Would you be able to take a look and provide an update for this issue?
As I've commented earlier in this thread, through testing i determined this issue was introduced in v5.4.0 (v5.3.1 works as expected). I took a look at that PR and noticed that there were a number of changes involving zone and runOutsideAngular which are likely to be the cause of this issue I think.
It's not strictly AngularFire, I was able to repro in my app when I updated the Firebase SDK. I will look into this but don't have a work around available yet.
A lot of what I've done with AFs Zone wrapping is defensive, but it's possible Firestore is setting up a timer, socket, or something outside of the scope.
In the future I am working to bring proper zone patching to Firebase, rather than all this Zone wrapping/unwrapping and messing with schedulers, but no ETA that I can share.
Could this be related to the long-polling behaviour? I've notice in the browser that when using .valueChanges() results in a series 60s long requests that listen for changes. This timing would be consistent with the 60s delay that we are experiencing in SSR mode. Perhaps there is a way to disable long-polling. I recall needing to mess with some of these firestore settings to get the firestore sdk to work with cypress.
Hmm so I went back an upgraded my app to firebase: 8.0.0 and @angular/fire: 6.0.4, to test my long polling question up above, and it appears as if the firestore hangs are fixed with this combination of versions. I'd recommend others in this thread try it out!
That's great. FWIW I'm now seeing AngularFireDatabase breaking Zone.js in conjunction with Firebase v8 instead...

@jadengis that's promising to hear. I am still getting the hang unfortunately on firebase 8.0.0 and @angular/fire: 6.0.4. I'll do some more testing though. Using rxjs take(1)/first causes hang still.
@odenman250 Are you using resolvers? I was experiencing this issue before using resolvers, but I recently switched to doing data fetching in guards and storing in ngxs store (because guards are run hierarchically and resolvers are not). Maybe that explains why I'm not seeing this issue any more. I _am_ using first in the guards.
I would also try adding firebase 8.0.0 and @angular/fire: 6.0.4 to your package.json and then nuking your package-lock.json and node_modules folder and reinstall everything from scratch. I was having some major issues until i tried that.
@jadengis thanks for that. Yeah I'm using resolvers. I just updated the test repo and nuked the package-lock.json and node_modules but still getting the hang in ssr. Repo here - https://github.com/odenman250/angularfire-ssr-test.
So seems like the observable isn't completing on server side still. I've tried with dev and prod builds as well. Good to know about the guards.
@jamesdaniels just FYI. Thanks.
As a newbie to Angular, I had the same issue. In my simple use case, however, I was able to solve the problem by manually subscribing to the observable:
this.afStore.collection('collectionName').doc('docName').valueChanges().subscribe( (data) => {
doSomethingWithData()
}
I did not try with pipes added, also I did not try if async-pipe works. I hope this "quick hack" helps some, that found this issue through google.
Also it seems the moment I call unsubscribe() on this subscription the page loads forever again.
I found the database zone issue that remained, it turns out making a ref has side-effects, so I had to wrap it to run outside of Angular. Please open a new issue if you find any additional zone issues.
@jamesdaniels awesome news, so is there a patch coming? Or what's the versions of firebase, angular fire, and angular we should be using for this to all work swimmingly?
Appreciate all the work here :)
I'd suggest Firebase 8.0.1 (or 8.0.3 when released, skip 8.0.2 as it has a bad bug with Firestore), AngularFire 6.1, and NG 10+.
AF 6.1 dropped last night with the most recent Zone.js fix for database.
thank you!
Wonderful news. Will test this and report if any. Thank you so much @jamesdaniels .. 馃憦
Still doesnt work ... :/
This workaround seems to help https://github.com/angular/angularfire/issues/2686#issuecomment-733144234
Still doesnt work ... :/
Same for me. I updated my test repo as per @jamesdaniels advise but still getting the hang (updated to Firebase 8.0.1 and AngularFire 6.1). Test repo link - https://github.com/odenman250/angularfire-ssr-test
@jamesdaniels Why are you closing this issue? It doesnt work with versions you mentioned
There are multiple related bugs. IMO I addressed the original issue reported here.
There are also work arounds.
Most helpful comment
I've got a quick update after a lot of debugging across different versions of
@angular/fire. I have discovered that this firestore hanging issue i described above (with the 60s timeout) was introduced in@angular/fire: 5.4.0.@angular/fire: 5.3.1does not experience this hanging issue. I tested both versions usingfirebase: 7.15.1which is the latest version.Looking at the patch notes for 5.4.0, it sounds like there was an overhaul to how zones are used in this library which I think would be consistent with symptoms we are all seeing.
I'm going to try to dig into the commits between those two version to see if I can find the regression.