nuxt-community / firebase-module

🔥 Easily integrate Firebase into your Nuxt project. 🔥
https://firebase.nuxtjs.org
MIT License
642 stars 98 forks source link

Nuxt Generate finished but did not exit #90

Closed ngblaylock closed 4 years ago

ngblaylock commented 4 years ago

This may not be an issue, but might be more of a question. When I run npm run generate I get the following error:

⚠ Nuxt Warning 

The command 'nuxt generate' finished but did not exit after 5s
This is most likely not caused by a bug in Nuxt.js
Make sure to cleanup all timers and listeners you or your plugins/modules start.
Nuxt.js will now force exit

DeprecationWarning: Starting with Nuxt version 3 this will be a fatal error  

I am not using Vuex, but I am using the onSnapshot method, which is what I have narrowed the issue down to. It appears that the onSnapshot method uses a listener which is causing the error. So I looked at the firebase docs and read the following - link:

var unsubscribe = db.collection("cities")
    .onSnapshot(function (){
      // Respond to data
      // ...
    });

// Later ...

// Stop listening to changes
unsubscribe();

So I tried to save the snapshot to something like this.destroySnapshot, then in the beforeDestroy lifecycle hook, call this.destroySnapshot(). However, when I run npm run generate again, it still gives me the same error.

So my real question is, is this an issue with Nuxt, Firebase, or me being a total noob? I am specifically worried about the line saying Starting with Nuxt version 3 this will be a fatal error

If you want to see my code, it is in my nuxt-sandbox repo.

And more than anything, thank you for creating Nuxt-Fire.

lxsedov commented 4 years ago

same here

lupas commented 4 years ago

Hey guys. I don't think this has anything to do with nuxt-fire as a module per se, but usage of Firebase+Nuxt generate in general.

It seems as if the routes get generated correctly and everything works as it should, but the error message gets generated since some recent Nuxt 2.x version.

The issue seems to show up in various situations when listeners are not destroyed before nuxt generate finishes:

1) When Using Firebase RealtimeDatabase

Brand new project, without nuxt-fire but by using a very simple nuxt-plugin as folllows:

// firebaseInit.js Plugin

import firebase from 'firebase/app'
import 'firebase/database'

const firebaseConfig = {
// Config
}

if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig)
}

export const fireDb = firebase.database() // --> This alone throws the error message.

The last line alone, without ever doing anything else, already throws the error message mentioned above.

2) When Using Firestore onSnapshot listeners

... will get to that soon

Similar Issues https://stackoverflow.com/questions/60124687/nuxt-generate-routes-by-firebase-data-is-finished-but-did-not-exit-after-5s

lupas commented 4 years ago

Possible Solution for Issue (1) (RealtimeDatabase)

I found this here:

When your app connects to the Firebase Database, it opens a web socket connection from the device to a Firebase server. This connection stays open for the lifetime of your app or until you call goOffline().

So when I do the following in the plugin above:

// firebaseInit.js Plugin

import firebase from 'firebase/app'
import 'firebase/database'

const firebaseConfig = {
// Config
}

if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig)
}

export const fireDb = firebase.database() // --> This alone throws the error mesage.

fireDb.goOffline() // <-- ADD THIS LINE
// of course this is not where we want to call goOffline already ;-)

Then the warning goes away.

So we can then further tap into the generate:done hook to call goOffline() after generate has finished:

// nuxt.config.js
import { fireDb } from './plugins/firebaseInit.js'

export default {
  hooks: {
    generate: {
      done(builder) {
        fireDb.goOffline()
      }
    }
  },
lupas commented 4 years ago

Issue (2) (Firestore .onSnapshot)

@ngblaylock & @lxsedov

Call .onSnapshot in mounted() instead of created() hook, that should solve the issue. This way the listener is not called twice on server and on client.

If you want to get initial data on SSR already, you should do a regular get() in the created() hook anyway.

lxsedov commented 4 years ago

thanks! can confirm .goOffline() works for Firebase Database

ngblaylock commented 4 years ago

Thanks @lupas. I can't believe I didn't try that, but it works perfectly. Apparently I don't know as much about the lifecycle hooks as I thought I did. I appreciate you looking into this for me, and hope it helps the rest of the community.

krisism commented 4 years ago

If looking for a similar solution with Firestore, you can use firedb.terminate() instead of 'goOffline()' in the nuxt.config.js hook mentioned above =) (Thanks for this thread, helped me a lot!)

lupas commented 4 years ago

@krisism Awesome, I was actually looking for that since the issue is also there with Firestore. Thanks for the tip!

Still trying to find a way to call this in the generate.done hook though since this.$fireStore is not accessible there..

https://github.com/nuxt-community/firebase-module/issues/93 is open for trying to fix this within this module.

simeon9696 commented 4 years ago

If looking for a similar solution with Firestore, you can use firedb.terminate() instead of 'goOffline()' in the nuxt.config.js hook mentioned above =) (Thanks for this thread, helped me a lot!)

I added the code as you suggested because I had the same error, then it fully crashed because 'it was already terminated'. Not sure what's happening there

dmvvilela commented 3 years ago

For those who still did not manage to fix this, nuxt firebase module has a config flag to terminate thing on generate: terminateDatabasesAfterGenerate: true

View doc here: https://firebase.nuxtjs.org/guide/options/