Search code examples
firebasewebpackgoogle-cloud-firestorereact-reduxgatsby

GatsbyJS with Firebase - WebpackError: ReferenceError: IDBIndex is not defined


I'm received error with gatsby develop. It's very similar to this one: https://github.com/firebase/firebase-js-sdk/issues/2222, but I'm received error with gatsby develop, not with gatsby build. I did a lot of research but I can't find working solution. At first I had a problem with gatsby build, like in this post: https://github.com/firebase/firebase-js-sdk/issues/2222, but I resolved it with custom onCreateWebpackConfig(you can find it below).

Stack: - Gatsby - Firebase(error probably with that) - Redux

I'm also delete .cache and node_modules and install everything again, but it didn't work.

Error:

There was an error compiling the html.js component for the development server.

See our docs page on debugging HTML builds for help https://gatsby.dev/debug-html ReferenceError: IDBIndex is not defined
]);
  86 | 
> 87 | proxyRequestMethods(Index, '_index', IDBIndex, [
     | ^
  88 |   'get',
  89 |   'getKey',
  90 |   'getAll',

  WebpackError: ReferenceError: IDBIndex is not defined

  - idb.mjs:87 Module../node_modules/idb/lib/idb.mjs
    node_modules/idb/lib/idb.mjs:87:1

  - index.esm.js:1 Module../node_modules/@firebase/installations/dist/index.esm.js
    node_modules/@firebase/installations/dist/index.esm.js:1:1

  - index.esm.js:1 Module../node_modules/@firebase/analytics/dist/index.esm.js
    node_modules/@firebase/analytics/dist/index.esm.js:1:1

  - index.esm.js:1 Module../node_modules/firebase/analytics/dist/index.esm.js
    node_modules/firebase/analytics/dist/index.esm.js:1:1

  - index.ts:1 Module../src/firebase/index.ts
    src/firebase/index.ts:1:1

  - index.esm.js:32 emit
    node_modules/@firebase/analytics/dist/index.esm.js:32:1

My gatsby-node file:

exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
  if (stage === 'build-html') {
    actions.setWebpackConfig({
      externals: getConfig().externals.concat(function(context, request, callback) {
        const regex = /^@?firebase(\/(.+))?/;
        if (regex.test(request)) {
          return callback(null, `umd ${request}`);
        }
        callback();
      }),
    });
  }
};

My firebase dependencies:

 "@firebase/firestore-types": "^1.10.1",
 "firebase": "^7.13.1",
 "firebase-admin": "^8.10.0",
 "firebase-functions": "^3.5.0",
 "firebase-tools": "^7.16.1",

Firebase index file:

import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';
import 'firebase/storage';
import 'firebase/analytics';
const firebaseConfig = {...};
firebase.initializeApp(firebaseConfig);
export const firestore = firebase.firestore();
export const auth = firebase.auth();
export const storage = firebase.storage();

Project repo: https://github.com/olafsulich/Projecty

Post on Github issues: https://github.com/firebase/firebase-js-sdk/issues/2946

Thanks in advance.


Solution

  • The following snippet will only work on build environment because of your condition (stage === 'build-html'):

       exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
          if (stage === 'build-html') {
            actions.setWebpackConfig({
              externals: getConfig().externals.concat(function(context, request, callback) {
                const regex = /^@?firebase(\/(.+))?/;
                if (regex.test(request)) {
                  return callback(null, `umd ${request}`);
                }
                callback();
              }),
            });
          }
        };
    

    Remove it and use it like this:

       exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
            actions.setWebpackConfig({
              externals: getConfig().externals.concat(function(context, request, callback) {
                const regex = /^@?firebase(\/(.+))?/;
                if (regex.test(request)) {
                  return callback(null, `umd ${request}`);
                }
                callback();
              }),
            });
        };
    

    Thank's a lot! It's working only on gatbsy develop, but now when I want to build project, I get an error - TypeError: Cannot read property 'concat' of undefined. You know how to solve it?

    Regarding the new issue, you can follow a workaround in this topic, This is a common error in third-party modules in Gatsby when they try to reach a DOM element (usually window) that is not already defined when the app builds. So, you need to wait until window is defined. You can achieve this in two ways:

    1. Instancing your firebase with a condition like this:

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

      Note the if (typeof window !== 'undefined') statement

    2. By ignoring firebase module in you webpack configuration like shows their docs. In your gatsby-node.js:

       exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
         if (stage === "build-html") {
           actions.setWebpackConfig({
             module: {
               rules: [
                 {
                   test: /bad-module/,
                   use: loaders.null(),
                 },
               ],
             },
           })
         }
       }
      

      Replace bad module for firebase (or the package/folder name in node_modules). Leave the slashes since test is a regular expression rule

      This snippet replaces your previous one that seems to throw an error in concat() function.


    For those who wants to try the concat() resolution, this will be helpful too:

    exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
      if (stage === 'build-html') {
        actions.setWebpackConfig({
          externals: getConfig().externals.concat((context, request, callback) => {
            const regex = /^@?firebase(\/(.+))?/
            // exclude firebase products from being bundled, so they will be loaded using require() at runtime.
            if (regex.test(request)) {
              return callback(null, `commonjs ${request}`) // <- use commonjs!
            }
            callback()
          }),
        })
      }
    }