angularfire: Route freezes with Resolver getting data from Firestore in SSR
Version info
Angular: 11.0.2
Firebase: 8.1.1
AngularFire: 6.1.2
Other (e.g. Ionic/Cordova, Node, browser, operating system): Chrome 87, Windows 10, Angular Universal, Node 12.14.1
How to reproduce these conditions
- Create Angular Universal app with Firebase
- Add Resolver that fetches data from Firestore to a lazy route
- Try navigating to that route in SSR
resolve({params}: ActivatedRouteSnapshot): Observable<any> {
console.log('Resolver');
return this.firestore
.doc(params['id'])
.get()
.pipe(
tap(() => console.log('Resolved')),
catchError(() => this.router.navigate(['']) && EMPTY),
);
}
I also added console.log('Constructor')
in that route’s component constructor.
Debug output
Console logs print out correctly:
Resolver
Resolved
Constructor
Expected behavior
Route opens with resolved data
Actual behavior
Route is stuck on loading, server does not return the page
Here comes the weird part
There’s a very strange way to kick-start it 😃
- Replace
doc
withcollection
in Resolver - Add some other request to Firestore in route’s component (doesn’t matter
doc
orcollection
) - Use
async
pipe in template to show that new request’s result
I’m very confused.
It’s hard to provide a reproduction, because it’s SSR. I’ll be happy to show it in my app if somebody is willing to live chat, it’s pretty straightforward.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 9
- Comments: 15 (3 by maintainers)
@Marcusg62, I was able to make your app serve the route from SSR - the issue is that you have several subscriptions and an angularfire auth subscription in your orderForm service, which is injected in your component. The auth subscription will never complete, and the other subscriptions don’t either.
Instead of using the behavior subject in your service, refactor it so that there are no subscriptions in it, and pass your
Restaurant
to yourinitializeOrderObject()
method. Only init the formGroup once and then usepatchValue()
on it in your initializeOrderObject method. Services have no lifecycle hooks so you can’t control subscriptions.Here’s how you can make it serve the restaurant route (you will need to later inject the service again after you remove all the subscriptions in it):
component:
template:
I am having the same issue. I have tried using promises as a workaround but no luck. Here is a link to my github repo with the bug. The route resolver is in
src/app/resolvers/restaurant.resolver.ts
The problem is with ssr, so just
npm i
andnpm run dev:ssr
Then copy paste this to your browser barlocalhost:4200/restaurant/bistroKing
The behavior is exactly as @waterplea describes, you go to the specific route (to be sure it uses SSR), and the browser just spins with no timeout. I don’t know why, but sometimes if you click into the bar again and hit enter while it was previously loading, it will then work without problem. See video:
https://user-images.githubusercontent.com/21998115/103108236-300df780-4603-11eb-920f-a11b83d2ab49.mov
@jamesdaniels what is
compat APIs
? Is there some place I can read about it? None of the workarounds mentioned are stable. Some of them work onng serve
but stop working once prod build is deployed, some work fordoc
but not forcollection
. And even then, I think, I had exactly the same workaround in two places in my app and one worked while another didn’t. Thankfully I really needed the one that worked and I just ditched the second one.I think the free demo ran out. Looks like a new firebase has to be created. And ssr function is created by default builder during ng deploy.
@inorganik I can’t believe I didn’t realize that the other subscriptions are the culprit. Thank so much!
More news. Looks like my hack doesn’t work once you build and deploy to Firebase 😦 EDIT: False alarm, hack still works, my issue was different.
I have found one other hack - run Resolver outside of Angular with NgZone. It all seems to work fine for
doc
, doesn’t help withcollection
. Both SSR and CSR work. Probably not a good idea for some reason, but I’ll have to stick with it until the issue is fixed.