Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v2] Cannot pass initializing Firebase app when building static HTML #6386

Closed
ng-hai opened this issue Jul 11, 2018 · 3 comments

Comments

@ng-hai
Copy link
Contributor

commented Jul 11, 2018

Description

I'm building an app integrated with Firebase, and implement a module like this

import firebase from 'firebase/app'
import 'firebase/auth'

const config = {
  apiKey: 'XXXXX',
  authDomain: 'XXXXX.firebaseapp.com',
  databaseURL: 'https://XXXXX.firebaseio.com',
  projectId: 'XXXXX',
  storageBucket: 'XXXXX.appspot.com',
  messagingSenderId: 'XXXXX',
}

class Firebase {
  constructor () {
    firebase.initializeApp(config)
    this.auth = firebase.auth()
  }
}

export default new Firebase()

There is no error when running Gatsby in development mode, but it appears when running Gatsby build at Building static HTML for pages step. It says:

Error: The XMLHttpRequest compatibility library was not found.

Steps to reproduce

Run gatsby build

Expected result

Pass the Building static HTML for pages step.

Actual result

Get error:

Error: The XMLHttpRequest compatibility library was not found.

Environment

System:
  OS: macOS High Sierra 10.13.5
  CPU: x64 Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
  Shell: 5.3 - /bin/zsh
Binaries:
  Node: 8.11.1 - /usr/local/bin/node
  Yarn: 1.7.0 - /usr/local/bin/yarn
  npm: 5.6.0 - /usr/local/bin/npm
Browsers:
  Chrome: 67.0.3396.99
  Safari: 11.1.1
npmPackages:
  gatsby: next => 2.0.0-beta.22 
  gatsby-plugin-no-sourcemaps: next => 2.0.0-beta.2 
  gatsby-plugin-react-helmet: next => 3.0.0-beta.3 
  gatsby-plugin-styled-components: next => 3.0.0-beta.2 
  gatsby-source-filesystem: ^1.5.39 => 1.5.39 
  gatsby-transformer-remark: ^1.7.44 => 1.7.44 

File contents (if changed)

gatsby-config.js:

module.exports = {
  siteMetadata: {
    title: 'Simple Trello',
  },
  plugins: [
    'gatsby-plugin-react-helmet',
    'gatsby-plugin-styled-components',
    'gatsby-plugin-no-sourcemaps',
    'gatsby-transformer-remark',
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'pages',
        path: `${__dirname}/src/pages/`,
      },
    },
  ],
}

package.json:

{
  "dependencies": {
    "firebase": "^5.2.0"
  }
}

gatsby-node.js:

const path = require('path')
const { createFilePath } = require('gatsby-source-filesystem')

exports.createPages = ({ actions, graphql }) => {
  const { createPage } = actions

  return new Promise(resolve => {
    createPage({
      path: '/',
      matchPath: '/:path',
      component: path.resolve('./src/app.js'),
    })

    graphql(`
      {
        allMarkdownRemark {
          edges {
            node {
              fields {
                slug
              }
            }
          }
        }
      }
    `).then(result => {
      result.data.allMarkdownRemark.edges.forEach(({ node }) => {
        createPage({
          path: node.fields.slug,
          component: path.resolve('./src/templates/blog.js'),
        })
      })
      resolve()
    })
  })
}

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions
  if (node.internal.type === 'MarkdownRemark') {
    const slug = createFilePath({
      node,
      getNode,
      basePath: 'pages',
      trailingSlash: false,
    })

    createNodeField({
      node,
      name: 'slug',
      value: slug,
    })
  }
}

gatsby-browser.js: N/A
gatsby-ssr.js: N/A

How I fix temporary

I wrap the Firebase initializing with checking window first and it passes the build step

class Firebase {
  constructor () {
    if (typeof window !== 'undefined') {
      firebase.initializeApp(config)
      this.auth = firebase.auth()
    }
  }
}

Is there any better workaround?

@dannywils

This comment has been minimized.

Copy link
Contributor

commented Jul 11, 2018

This is expected because window is not defined during build. See reason 1 in https://www.gatsbyjs.org/docs/debugging-html-builds/

Your workaround seems fine to me. Alternatively you could use export the class and only instantiate in the componentDidMount() lifecycle method which only executes on the client where window is available.

You may also want to use the singleton pattern to ensure you reuse the same instance throughout your app.

Example:

class Firebase {
  static instance;
  constructor() {
    if (instance) {
      return instance;
    }
    firebase.initializeApp(config);
    this.auth = firebase.auth();
    this.instance = this;
  }
}

export default Firebase;

and then used in your components:

import Firebase from './firebase';

class MyComponent extends React.Component {
  componentDidMount() {
    this.firebase = new Firebase();
  }

  render() {
    // ...
  }
}
@ng-hai

This comment has been minimized.

Copy link
Contributor Author

commented Jul 11, 2018

Thanks, @dannywils, in my case I want to use Firebase outside components, like initialize default context state

import Firebase from './firebase'

const initialState = {
  signIn: Boolean(Firebase.auth.currentUser)
}

const { Provider, Consumer } = React.createContext(initialState)

class AuthContext extends React.PureComponent {
  // ...
}
@dannywils

This comment has been minimized.

Copy link
Contributor

commented Jul 11, 2018

In that case your workaround is perfectly fine. If you want to move the window check outside of your class, you can move it to where you use Firebase for the first time.

import Firebase from './firebase';

let initialState = { signIn: false };

if (typeof window !== 'undefined') {
  const firebase = new Firebase();
  initialState = Boolean(firebase.auth.currentUser);
}

const { Provider, Consumer } = React.createContext(initialState);

class AuthContext extends React.PureComponent {
  // ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.