alexluong / gatsby-packages

Gatsby packages
MIT License
56 stars 24 forks source link

WebpackError: TypeError: gatsby_plugin_firebase__WEBPACK_IMPORTED_MODULE_0__.d efault.firestore is not a function #23

Open AvilaAi opened 4 years ago

AvilaAi commented 4 years ago

I'm trying to use firestore and have imported it in both brower.js and ssr.js, it works in develop, but i got this issue when build:

failed Building static HTML for pages - 13.183s

 ERROR #95313

Building static HTML failed

See our docs page for more info on this error: https://gatsby.dev/debug-html

  1 | import firebase from "gatsby-plugin-firebase"

> 20 | const db = firebase.firestore()
     |                     ^
  21 |
  22 | const getGeohashRange = (
  23 |   latitude,

  WebpackError: TypeError: gatsby_plugin_firebase__WEBPACK_IMPORTED_MODULE_0__.d  efault.firestore is not a function

As mentioned in another issue that no need to import the pacakge in ssr.js, i tried but still not working, anyone can help? thanks

AvilaAi commented 4 years ago

problem solved, just use

firebase
    .firestore()
    .collection("film")

instead of

const db= firebase.firestore()
db.collection("film")..
fmontes commented 4 years ago

Didn't work for me.

mikan3rd commented 4 years ago

Similar problem occurred when building.

firebase.auth()

WebpackError: TypeError: gatsby_plugin_firebase__WEBPACK_IMPORTED_MODULE_1__.default.auth is not a function

I can fix it by adding import "firebase/auth", but that was not specified in the document.

Noah-Huppert commented 4 years ago

I am running into the same problem, but with any of the services (ie firebase.messaging(), firebase.firestore(), ect).

My project's gatsby-browser.js file:

import "firebase/auth";
import "firebase/firestore";
import "firebase/messaging";
import "firebase/functions";

My Gatsby page which uses the Firebase plugin:

import firebase from "gatsby-plugin-firebase";

const Page = () => {
  firebase.firestore();
};

export default Page;

When I run gatsby develop my page everything works.
However when I run gatsby build (For production) I get the error above.

I added a console.log statement to node_modules/gatsby-plugin-firebase/src/firebase.js at the top after the imports and:

console.log("FIREBASE.APPS=", firebase.apps);

and the output is: FIREBASE.APPS= [].

Not sure why it is working in the development builds but not production builds...

None of the fixes suggested above work either.

Noah-Huppert commented 4 years ago

I went through all the trouble of using Firebase in my app without this plugin, and then I got the same error. So this must be related to the way Firebase is imported or used generally...

Noah-Huppert commented 4 years ago

Ok I found 2 definite fixes.

As far as I can tell the reason this is happening is that during the build HTML stage the imports you put in your own gatsby-browser.js and gatsby-ssr.js files are not used. Because we are in the NodeJs environment. As a result all the Firebase API client factory methods like firebase.auth(), firebase.functions(), ect are not available.

If You Are Using Hooks And Need To Use Hooks

Wrap your usage of Firebase in useEffect(). If you can't use useEffect() then make your component not use Firebase at all if Gatsby is in the build HTML stage.

If you can't use useEffect() then do something like this:

import React from "react";
import firebase from "gatsby-plugin-firebase";
import { isNode } from "@firebase/util";

const FirebaseContext = React.creactContext({});

const FirebaseProvider = ({children}) => {
  // If in the Gatsby build HTML stage 
  // don't do anything with Firebase
  if (isNode() === true) {
    return children;
  }

  // Otherwise, use Firebase normally
  return (
    <FirebaseContext.Provider value={{
      functions: firebase.functions(),
      auth: firebase.auth()
    }}>
      {children}
    </FirebaseContext.Provider>
  );
};

If You Are Using React Component Classes

Don't use Firebase in the render() method. In my case moved my usage to the componentDidMount() method and the problem was fixed.

davwheat commented 4 years ago

Can confirm this is also an issue for me.

alexluong commented 4 years ago

Noah's answer is spot-on. I don't really have anything else to add.

Let me know if what they said doesn't work for you and I can answer on a more case-by-case basis. Thanks folks!

davwheat commented 4 years ago

One issue is that I'm using this with the react firebase hooks package. This problem changes my nice one line into an absolute mess, because hooks can't be used in useEffect callbacks.

const [user, loading, error] = useAuthState(firebase.auth())

I might just fork that package and edit it to make the changes there.

alexluong commented 4 years ago

Yeah, in this use case I don't think there's anything I can do to help with the integration with react-firebase-hooks. May worth opening an issue over there?

davwheat commented 4 years ago

I decided to just fork it and make it compatible: react-gatsby-firebase-hooks


Whatever I tried just broke it more and more... I just used useEffect in the end.

div-cowboy commented 4 years ago

I'm still having issues with this even after reformatting my code to match @Noah-Huppert's.

My code works in development but throws an error that one of my context functions is not actually a function when I call isLoggedIn in my header component. Even with the isNode() code, Gatsby tries to access stuff from my Firebase context during the static page generation. Would appreciate any help with this:

Firebase Provider carbon

Header carbon (1)

Error carbon (2)

alexanderjsx commented 4 years ago

Clean code for auth:

import React, { useState, useEffect } from 'react';
import firebase from 'gatsby-plugin-firebase';

export default () => {
  const { auth } = firebase;
  const [user, setUser] = useState();
  useEffect(() => auth().onAuthStateChanged(setUser), []);

  const login = () => auth().signInWithPopup(new auth.GoogleAuthProvider());
  const logout = () => auth().signOut();

  if (!user) return <div>no user :/</div>;

  const { isAnonymous, displayName } = user;

  return (
    <div>You logged in as {isAnonymous ? 'Anonymous' : displayName}. {isAnonymous
      ? <Button onClick={login}>login with Google</Button>
      : <Button onClick={logout}>Logout</Button>}
    </div>
  );
};
bennchong commented 4 years ago

I am having issues now with the library 'react-firebase-hooks', where even in gatsby develop firestore is not a function.

krishna-acondy commented 3 years ago

@Noah-Huppert Thanks for the fix you suggested. Worked great for me! 🙌🏽

I have a small addition - when you're using the FirebaseContext in combination with react-firebase-hooks, gatsby build will still complain if you haven't provided a value via the FirebaseContext.Provider.

I was able to get past that by providing a no-op firebase object like so:

const NoOpFirebase = {
  firestore: () => ({
    collection: () => ({
      where: () => null
    })
  })
}

export const FirebaseProvider = ({children}) => {
  // If in the Gatsby build HTML stage 
  // don't do anything with Firebase
  if (isNode() === true) {
    return (
      <FirebaseContext.Provider value={NoOpFirebase}>
        {children}
      </FirebaseContext.Provider>
    );
  }

  // Otherwise, use Firebase normally
  return (
    <FirebaseContext.Provider value={firebase}>
      {children}
    </FirebaseContext.Provider>
  );
};