Search code examples
javascriptangularangularfire2

Angular Universal, app will not load until clicking 'refresh' twice


I'm building an Angular Universal App. I recently added a route resolver and started seeing this weird behavior where when I run npm run dev:ssr, the page won't load until I click the reload button twice.

1st: click: browser spins and doesn't seem to timeout...

2nd click: page loads

Here is my github repo. I suspect it has something to do with my route resolver which simply fetches data from Firestore and places it in the TransferState. Here's the resolver for convenience:

import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { Observable, of } from 'rxjs';
import { isPlatformServer } from '@angular/common';
import { makeStateKey, TransferState } from "@angular/platform-browser";
import { Restaurant } from '../restaurants/Interfaces.model';
import { AngularFirestore } from '@angular/fire/firestore';
import { first, tap } from 'rxjs/operators';


@Injectable()
export class RestaurantResolver implements Resolve<Restaurant> {

    constructor(
        public afs: AngularFirestore,
        private transferState: TransferState,
        @Inject(PLATFORM_ID) private platformId) {

    }

    async resolve(route: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Promise<Restaurant> {

        console.log('platformId', this.platformId)

        const rId = route.url[1].path;

        const restaurantId = makeStateKey<Restaurant>("restaurant-" + rId);

        if (this.transferState.hasKey(restaurantId)) {

            console.log('has key', restaurantId)


            const restaurant = this.transferState.get(restaurantId, null);

            this.transferState.remove(restaurantId);

            return restaurant;
        }
        else {

            let result: Restaurant = (await this.afs.doc('restaurants/' + rId).get().toPromise()).data() as Restaurant
            if (isPlatformServer(this.platformId)) {
                this.transferState.set(restaurantId, result);
            }
            return result;
        }
    }
}

Solution

  • It turns out there is a bug in the AngularFire library where observables are not completing, this the given behavior.