nuxt-community / firebase-module

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

SSG: Getting auth to initialize before running fetches #487

Closed MarkSonn closed 3 years ago

MarkSonn commented 3 years ago

Hi guys,

TLDR: Is there a place that I can put this.$fire.auth.currentUser and/or this.$fire.auth.onAuthStateChanged(...) in my static Nuxt app such that they finish execution and save the user object to my Vuex store before the fetch hooks are are run on the pages?


I'm trying to use Firebase Auth on my statically generated Nuxt web app. I have boiled down the problem I am experiencing to the simplest form I can below.

My desired behaviour is to capture the firebase auth user object of the person using the app if they already have a live auth session. I can then use this user object to get their uid and use fetch on the app pages to get their data from Firestore as follows:

fetchOnServer: false,
async fetch () {
  const uid = this.$store.state.user?.uid
  const response = await this.$fire.firestore.collection('whatever').doc(uid).get()
  // Do whatever I want with the data
},

The issue I have is that no matter what I do, I can't get the user to be initialized before these fetch hooks are run. I have tried putting this.$fire.auth.currentUser and this.$fire.auth.onAuthStateChanged(...) in many places to try and get them to finish running before the fetches on the pages run.

I have managed to get these user checks to start execution, then the fetch hooks are called, then the user checks finish execution, and then the user object is set. This is too late for the fetches to get the right data.

Yes, I'm aware I can move these calls from fetch hooks to other hooks. I am open to these answers if they are best practice or the only way, however, I was hoping to find a solution keeping them in the fetch hook because of prefetching and consistency with the rest of my app.

MarkSonn commented 3 years ago

The answer is to make a blocking client only plugin as follows:

  1. Make a plugin in the plugins directory. I called mine authInit.client.js (but you can change the bit before the first dot)

  2. Add this code to that file:

    export default async (context) => {
    const promise = new Promise((resolve, reject) => {
    const unsubscribe = context.app.$fire.auth.onAuthStateChanged((user) => {
      unsubscribe()
      resolve(user)
    }, reject)
    })
    
    await promise
    }
  3. Include it in nuxt.config.js under plugins as follows:

    { src: '~/plugins/authInit.client.js', ssr: false }