How to initialize firebase in gatsby?

99封情书 提交于 2020-06-27 14:31:30

问题


I'm stuck on making firebase work in my gatsby application that uses Redux with Redux-sagas. I know about the existence of firebase-sagas but I'm trying to make without using it.

I'm trying to init firebase auth by:

import * as firebase from 'firebase/app';
import 'firebase/auth';

export const app = firebase.initializeApp(
  {
    apiKey        : "apiKey",
    authDomain    : "project.firebaseapp.com",
    databaseURL   : "https://project.firebaseio.com",
    projectId     : "project",
    storageBucket : "project.appspot.com",
    appId         : "appId"
  }

)

export const authRef = () => app.auth(); //also tried: firebase.auth() and firebase.auth(app)
//firebase.auth returns a function, but firebase.auth() throws error

I have the following config on my gatsby-node.js:

const path = require('path');

exports.onCreateWebpackConfig = ({ actions, plugins, loaders, getConfig }) => {
  const config = getConfig()

  config.resolve = {
    ...config.resolve,
      mainFields: ['module', 'browser', 'main'],
      alias: {
        ...config.resolve.alias,
        ['firebase/app']       : path.resolve(__dirname, 'node_modules/firebase/app/dist/index.cjs.js'),
        ['firebase/auth']      : path.resolve(__dirname, 'node_modules/firebase/auth/dist/index.cjs.js'),
      }
  }

  actions.replaceWebpackConfig(config)
}

It trows the error:

{ [M [Error]: The XMLHttpRequest compatibility library was not found.]
  code: 'auth/internal-error',
  message: 'The XMLHttpRequest compatibility library was not found.' }

I think it's some problem related to webpack. I would love any insights on this problem :)


回答1:


As Gatsby builds pages in a server environment, you can't access Firebase during Gatsby build time. Firebase calls (using the Web SDK) have to happen when the user is on a browser/client environment.

One solution to this problem is creating a function like so:

firebase.js:

import firebase from '@firebase/app';
import '@firebase/auth';
import '@firebase/firestore';
import '@firebase/functions';

const config = {
   ... firebase config here
};

let instance;

export default function getFirebase() {
  if (typeof window !== 'undefined') {
    if (instance) return instance;
    instance = firebase.initializeApp(config);
    return instance;
  }

  return null;
}

This file returns a function, which returns an instance of Firebase if the user has the global window available (e.g. on the browser). It also caches the Firebase instance to ensure it cannot be reinitialised again (in case of the user changing page on your website).

In your components, you can now do something similar to the following:

import getFirebase from './firebase';

function MyApp() {
  const firebase = getFirebase();
}

As Gatsby will try to build this page into HTML during gatsby build, the firebase const will return null, which is correct, as the Firebase Web SDK cannot initialise on a server environment. However, to make use of Firebase on your website, you need to wait until Firebase is available (so the user has to have loaded your website), so we can make use of Reacts useEffect hook:

import React { useEffect } from 'react';    
import getFirebase from './firebase';

function MyApp() {
  const firebase = getFirebase();

  useEffect(() => {
    if (!firebase) return;

    firebase.auth().onAuthStateChanged((user) => { ... });
  }, [firebase]);
}

This works as Firebase is being used in a browser environment and has access to the browser, which is needed for the Web SDK to work.

It does have drawbacks; your compo have to return null in instances when you need Firebase to display content, which will mean your HTML build on the server will not contain any HTML, and it'll be injected via the client. In most cases though, such as an account page, this is fine.

If you need access to data from say Cloud Firestore to display page content, you're best using the Admin SDK to fetch content and add it to GraphQL during Gatsby build. That way it will be available on the server during build time.

Sorry if that was a waffle or not clear!



来源:https://stackoverflow.com/questions/58246333/how-to-initialize-firebase-in-gatsby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!