Как инициализировать FireBase в Гэтсби? - PullRequest
2 голосов
/ 05 октября 2019

Я застрял, чтобы заставить firebase работать в моем приложении gatsby, которое использует Redux с Redux-sagas. Я знаю о существовании firebase-sagas, но я пытаюсь сделать без его использования.

Я пытаюсь инициировать аутентификацию firebase с помощью:

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

У меня есть следующий конфигна моем 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)
}

Выдает ошибку:

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

Я думаю, что это некоторая проблема, связанная с веб-пакетом. Я хотел бы получить любую информацию по этой проблеме:)

1 Ответ

3 голосов
/ 05 октября 2019

Поскольку Gatsby создает страницы в серверной среде, вы не можете получить доступ к Firebase во время сборки Gatsby. Вызовы Firebase (с использованием Web SDK) должны выполняться, когда пользователь находится в среде браузера / клиента.

Одним из решений этой проблемы является создание такой функции:

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;
}

Этот файл возвращает функцию, которая возвращает экземпляр Firebase, если пользователю доступен глобальный window (например, в браузере). Он также кэширует экземпляр Firebase, чтобы гарантировать, что он не может быть повторно инициализирован повторно (в случае, если пользователь изменяет страницу на вашем веб-сайте).

В ваших компонентах вы можете теперь сделать что-то похожее на следующее:

import getFirebase from './firebase';

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

Поскольку Gatsby будет пытаться встроить эту страницу в HTML во время gatsby build, констант firebase вернет ноль, что является правильным, поскольку Firebase Web SDK не может инициализироваться в серверной среде. Однако, чтобы использовать Firebase на вашем сайте, вам нужно подождать, пока Firebase станет доступным (чтобы пользователь загрузил ваш сайт), чтобы мы могли использовать ловушку Reacts useEffect:

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

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

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

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

Это работает, поскольку Firebase используется в среде браузера и имеет доступ к браузеру, который необходим для работы Web SDK.

У него есть недостатки;ваша компоновка должна возвращать null в тех случаях, когда вам нужен Firebase для отображения контента, что будет означать, что ваша HTML-сборка на сервере не будет содержать HTML, и она будет внедрена через клиента. Однако в большинстве случаев, например, на странице account, это нормально.

Если вам нужен доступ к данным, например, из Cloud Firestore, для отображения содержимого страницы, лучше всего использовать Admin SDK для получения содержимого идобавьте его в GraphQL во время сборки Gatsby. Таким образом, он будет доступен на сервере во время сборки.

Извините, если это была вафля или неясно!

...