如何在 gatsby 中初始化 firebase? [英] How to initialize firebase in gatsby?

查看:18
本文介绍了如何在 gatsby 中初始化 firebase?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直坚持在使用 Redux 和 Redux-saga 的 gatsby 应用程序中使用 firebase.我知道 firebase-sagas 的存在,但我正在尝试不使用它.

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.

我正在尝试通过以下方式初始化 firebase 身份验证:

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

我的 gatsby-node.js 上有以下配置:

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

它会引发错误:

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

我认为这是与 webpack 相关的一些问题.我希望对这个问题有任何见解:)

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

推荐答案

由于 Gatsby 在服务器环境中构建页面,因此您无法在 Gatsby 构建期间访问 Firebase.Firebase 调用(使用 Web SDK)必须在用户处于浏览器/客户端环境中时发生.

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:

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

此文件返回一个函数,如果用户具有可用的全局 window(例如在浏览器上),则该函数返回 Firebase 的一个实例.它还缓存 Firebase 实例以确保它无法再次重新初始化(以防用户更改您网站上的页面).

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

由于 Gatsby 会在 gatsby build 期间尝试将此页面构建为 HTML,firebase const 将返回 null,这是正确的,因为 Firebase Web SDK 无法初始化服务器环境.但是,要在您的网站上使用 Firebase,您需要等到 Firebase 可用(因此用户必须加载您的网站),因此我们可以使用 Reacts useEffect hook:>

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

这是因为 Firebase 在浏览器环境中使用并且可以访问浏览器,这是 Web SDK 工作所必需的.

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.

它确实有缺点;当您需要 Firebase 显示内容时,您的组件必须返回 null,这意味着您在服务器上的 HTML 构建将不包含任何 HTML,它将通过客户端注入.但在大多数情况下,例如 account 页面,这很好.

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.

如果您需要访问来自 Cloud Firestore 的数据以显示页面内容,最好使用 Admin SDK 来获取内容并将其在 Gatsby 构建期间添加到 GraphQL.这样它就可以在构建期间在服务器上使用.

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!

这篇关于如何在 gatsby 中初始化 firebase?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆