Skip to content

Integration with Angular Universal #191

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ghost opened this issue May 25, 2016 · 17 comments
Closed

Integration with Angular Universal #191

ghost opened this issue May 25, 2016 · 17 comments

Comments

@ghost
Copy link

ghost commented May 25, 2016

It just works, except for one thing

WARNING: your application is taking longer than 2000 Zone turns.

(universal-starter)

I guess it is because the connection that angular does with firebase remains open.

On the server, when we are done fetching data from firebase, somehow we need to close the connection, but I don't know if this can be achieved with the current angularfire2 version.

@davideast
Copy link
Collaborator

I'm not a Universal expert so I'll be summoning @jeffwhelpley.

Jeff, is there something we need to do to integrate well with Universal?

@jeffwhelpley
Copy link

Ah, yes. OK, so the short answer here is that we will need to make an adjustment to AngularFire so that (as @mmgdort suspects) the server version must immediately close the connection after getting the initial data set.

The longer explanation is that on the server side we use zones to wait for all async operations up to 2 seconds. We put in a timeout so that the server code would never hang. So, what I would strongly suggest are the following changes:

  • Automatically close connections after getting initial data
  • No-op calls that are meant for longer time periods
  • You can implement this either through DI swapping (i.e. have a different server version of AngularFire that people import instead of the standard) or monkey patching

Let me know if you have any questions on this.

@doczoidberg
Copy link

@mmgdort how do I have to configure Firebase on the server?

@msegers
Copy link

msegers commented Aug 17, 2016

Heya, as of right now implementing AngularFire2 into my Universal project should just work? Warnings aside of course. "Keeps connection open" does this mean that in the end we'll have a huge memory leak going on or is it only one session which remains active, and is actually a good thing?

Just interested as I'm implementing AF in a personal universal project

@leandroz
Copy link

Any updates on this? Is there a list of things to do where I can help?

I just started a project with Angular Universal and AngularFire2 so I don't mind investing some time learning the core.

Aside the initial connection problem, I saw a WindowLocation that is using window.location.

@leandroz
Copy link

I am initializing the app in both node and browser modules, which causes this error: Firebase App named '[DEFAULT]' already exists.

I tried setting different names with the same configurations but the server never responds and hangs indefinitely.

@jeffwhelpley
Copy link

jeffwhelpley commented Sep 23, 2016

In many cases Firebase is only being used on the client side for realtime data. If that is the case, then you can abstract out your service that references Firebase so it is not used at all on the server side.

If, however, you are trying to just get that initial snapshot of data from Firebase for your server rendered view, then yes there does need to be some changes. Specifically, I think there are two key pieces to enable this:

  1. Ensure the Firebase libs don't reference any DOM apis and/or provide the appropriate patches so they work on the server side
  2. Add a new zone.js patch that will ensure server rendering will wait until the first Firebase snapshot is complete

For the second point, basically you need to do something like this:

https://github.com/angular/zone.js/blob/master/lib/node/node.ts#L65

That code is used to help Angular Universal keep track of all the http calls on the server and wait for them to complete before returning a rendered page. We need something similar for the Firebase APIs as appropriate.

@gdi2290 @davideast please weigh in with your two cents.

@leandroz
Copy link

@jeffwhelpley thanks for the answer!

Yes the basic idea is to have the data in the server before doing the first render.

The firebase lib has a node version so that shouldn't be a problem.
If Angular Universal is already working with http calls, I can create a parent service and then for the server use a http implementation with the Firebase API directly, and in the browser use Angular
Fire2.

How much work would be to create a version of AngularFire2 specific for the server that uses Angular Http service?

@jeffwhelpley
Copy link

If you are doing http to Firebase, then there shouldn't be any issue (let me know if there is). I am guessing that under the scenes Firebase is not using straight http calls, though, because it tries to set up a socket connection, right? So, basically the trick is either just do straight http calls if you run Firebase on the web server for universal rendering (in which case the existing zone.js implementation will work) OR if you use the socket connection, you have to build a new zone.js patch which will wait for the initial snapshot and then automatically close the socket.

All that said, I haven't tried this out, so there may be other issues I am not thinking about once you get into things. Does that make sense?

@leandroz
Copy link

It makes perfect sense, I will try with the http approach and make an update if I found issues!

Thanks!

@orangesoup
Copy link

@leandroz Please tell us how it goes, I have the same problem, otherwise my app would work. To be honest this feels quite a lot of work to me (at least in my case), so if there is any other approach that would be nice!

@katowulf
Copy link
Contributor

katowulf commented Sep 27, 2016

The Firebase web SDK isn't going to work server-side. However, the node.js installation should.

you can abstract out your service that references Firebase so it is not used at all on the server side.

Depending on the use case, which I don't really understand, if the SDK is already abstracted, one could just use the Firebase REST API to make static calls. Alternately, simply initializing the node version with a service account on the server would allow the same real-time calls to be used in both.

@doczoidberg
Copy link

any news on this topic?

@tskweres
Copy link

tskweres commented Mar 8, 2017

Would love to use AngularFire with Universal, any updates?

@samvloeberghs
Copy link

samvloeberghs commented May 9, 2017

hi @davideast (@tskweres) I've been upgrading my project to use the latest 4.0.0-rc.0 release.
Any updates on how to properly stub the AngularFireAuth module for the server module?

Currently I use the same approach as I did here: angular/universal-starter#127 (comment)
Some official recommendations might be good ..

@ValentinFunk
Copy link
Contributor

I got it working with universal with a lot of hacking - auth didn't really require any changes, just using Webpack to replace imports to user firebase-node and ignore the angularfire2/* imports. What I had to do is add an endpoint in server to create a custom token from id token and store that as cookie. Server injects REQUEST, reads the cookie and logs into firebase using the custom token.

For database I needed to patch database.ts and run the call to app.database() in runOutsideAngular(). Then i manually wrap services to create a zoneTask until the first item has been emitted:

class SomeService {
    getObject(ref) {
        const object$ = this.database.object(ref);
        if (UNIVERSAL) {
            const task = Zone.current.scheduleMacroTask('authService', () => {}, {}, () => {}, () => {});
            object$.first().subscribe(() => task.invoke());
        }
        return object$;
    }
}

I haven't used this in a very large app yet so there might be some limitations - but it does work :)

@davideast
Copy link
Collaborator

Follow #1073 for the modern version of this issue. There are plans for SSR support, but it's not here just yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants