6 votes

Comment initialiser firebase dans gatsby ?

J'ai du mal à faire fonctionner firebase dans mon application gatsby qui utilise Redux avec Redux-sagas. Je connais l'existence de firebase-sagas mais j'essaie de le faire sans l'utiliser.

J'essaie d'initier l'authentification firebase par :

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

J'ai la configuration suivante sur mon 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)
}

Il affiche l'erreur :

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

Je pense qu'il s'agit d'un problème lié à webpack. J'aimerais avoir des informations sur ce problème :)

13voto

Elliot Hesp Points 379

Comme Gatsby construit des pages dans un environnement serveur, vous ne pouvez pas accéder à Firebase pendant le temps de construction de Gatsby. Les appels à Firebase (à l'aide du SDK Web) doivent avoir lieu lorsque l'utilisateur se trouve dans un environnement navigateur/client.

Une solution à ce problème consiste à créer une fonction comme celle-ci :

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

Ce fichier renvoie une fonction, qui renvoie une instance de Firebase si l'utilisateur possède la propriété globale window disponible (par exemple sur le navigateur). Il met également en cache l'instance Firebase afin de s'assurer qu'elle ne peut pas être réinitialisée (au cas où l'utilisateur changerait de page sur votre site web).

Dans vos composants, vous pouvez maintenant faire quelque chose de similaire à ce qui suit :

import getFirebase from './firebase';

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

Comme Gatsby essaiera de construire cette page en HTML pendant gatsby build , le firebase const retournera null, ce qui est correct, car le Firebase Web SDK ne peut pas s'initialiser sur un environnement serveur. Cependant, pour utiliser Firebase sur votre site web, vous devez attendre que Firebase soit disponible (l'utilisateur doit donc avoir chargé votre site web), ce qui nous permet d'utiliser Reacts useEffect crochet :

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

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

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

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

Cela fonctionne car Firebase est utilisé dans un environnement de navigateur et a accès au navigateur, ce qui est nécessaire pour que le SDK Web fonctionne.

Il y a des inconvénients : votre compo doit être renvoyée. null dans les cas où vous avez besoin de Firebase pour afficher du contenu, ce qui signifie que votre construction HTML sur le serveur ne contiendra pas de HTML, et qu'il sera injecté via le client. Dans la plupart des cas cependant, comme dans le cas d'un account c'est très bien.

Si vous avez besoin d'accéder à des données provenant par exemple de Cloud Firestore pour afficher le contenu d'une page, il est préférable d'utiliser le SDK d'administration pour récupérer le contenu et l'ajouter à GraphQL pendant la construction de Gatsby. De cette façon, il sera disponible sur le serveur au moment de la construction.

Désolé si ce n'était pas clair ou si c'était un peu confus !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X