Using Firebase in Electron: Tips and Tricks

Christina Holland
Firebase Developers
5 min readNov 21, 2019

--

Electron and Firebase can be a great combination that allows a developer to quickly build a desktop app for multiple platforms (using Electron) and connect it to realtime cloud data and authentication using Firebase. Electron has been used to develop popular apps such as Slack, Skype, and Visual Studio Code, and deliver them simultaneously to users on Windows, MacOS, and Linux. Firebase’s JavaScript SDK is a natural fit to connect these apps to the cloud.

Due to some unique aspects of Electron’s environment, however, there are a few recurring snags that developers often run into when integrating Firebase.

While the Firebase team doesn’t officially offer official support for Firebase in Electron, here are a few tips to avoid some of the most frequently reported problems.

Overview

Electron effectively has 3 types of environments Firebase could potentially be loaded into:

  • The main process
  • A renderer process (with nodeIntegration = true)
  • A renderer process (with nodeIntegration = false)

The main process is a pure Node process. It is the initial process that launches one or more renderer processes.

A renderer process is mostly a browser process which, by default, also has access to some basic Node APIs like require, fs, process, etc. It can be launched with:

  • nodeIntegration = true This is the default and doesn’t need to be specified. In default mode, the renderer process is a browser process with some Node capabilities.
  • nodeIntegration = false If this option is set when launching the renderer process, Node capabilities are disabled and the renderer process acts more or less like a pure browser environment.

Some Firebase components work differently or not at all in a Node environment. Most Electron/Firebase users would probably prefer to use Firebase in a renderer process, using it as they would in a browser. The tricky thing is that since the renderer process is (when using default settings) a partial Node process, this can cause Firebase to think it’s in a Node environment.

The other main cause of conflicts with Firebase and Electron seems to be that many Electron apps load pages locally with the file:// protocol instead of http://, which makes OAuth complicated.

Issues Caused By Firebase Not Recognizing The Render Process as a Browser Environment

  • Firebase Authentication: If Firebase does not recognize it is in a browser environment, signInWithPopup and signInWithRedirect will not work. Note there are a few other requirements to getting those methods to work, such as serving the page with the http or https protocol and setting the nativeWindowOpen property. See below for more.
  • Firebase Realtime Database: In a Node environment, Realtime Database falls back to a third-party library for websocket functionality which may not work as well as native websockets.
  • Firestore: In a Node environment, Firestore uses gRPC. This can work in all types of Electron environments but you may see this error at first:
    Failed to load gRPC binary module because it was not installed for the current system”
    This happens because gRPC has been installed by npm for Node but not for Electron. If for some reason you do want to use Firebase in a Node environment (for example, in the main process), this can be fixed by rebuilding gRPC for your Electron version. Use npm rebuild — runtime=electron — target=2.0.0 or use electron-rebuild.
  • Firebase Cloud Messaging: The Firebase Web SDK for Messaging isn’t available in a Node environment.
  • Firebase Cloud Storage: The Firebase Web SDK for Storage isn’t available in a Node environment.

Getting Firebase to Recognize a Browser Environment

Firebase determines whether it’s in a Node environment by which Firebase bundle is being used. We ship different bundles for different environments, specified in the package.json of each individual package and in the all-in-one Firebase package as main for Node, browser for CommonJS browser-targeted modules, and module for ES browser-targeted modules.

The package.json of @firebase/app

If your project does not use a bundler (such as Webpack or Rollup), and your render process code directly imports Firebase with require, this will result in the standard Node behavior of bringing in the file specified in main, which is the Node version of Firebase. To avoid this, the best solution is probably to use a bundler and explicitly prioritize the browser field (Solution 1, below). If this isn’t possible, you can bring in Firebase packages as UMD modules using script tags (see Solution 2).

Solution 1: Using a Bundler

If your project uses a bundler, the project’s bundler config determines which of these Firebase bundles gets bundled into the final files. Setting the bundler’s config to prioritize the browser field over main will ensure the browser version of Firebase gets into your bundle, and Firebase will behave as if in a browser environment.

Consult your specific bundler’s documentation on how to set the priority of these fields.

Solution 2: Including Firebase With Script Tags

UMD package bundles can be imported like this (for an app that uses Firebase Authentication, Cloud Storage, and Cloud Firestore):

Your script can then access firebase as a global variable.

Issues with signInWithPopup() or signInWithRedirect()

There are several issues that make signInWithPopup or signInWithRedirect tricky.

First, it won’t work in a Node environment, so you need to make sure the Firebase browser version is being loaded (see above).

Second, for popups, webPreferences.nativeWindowOpen needs to be set to true when initializing this BrowserWindow (i.e. render process). This allows use of the native window.open() method, which is needed to open popups.

Third, OAuth requests need to have a verifiable origin, which can be whitelisted in the Firebase Console. This requires the current Electron browser window to use the http or https protocol, and not file. That means the current window contents should be loaded with browserWindow.loadURL and not browserWindow.loadFile, and the url must be an http or https url, not a file:// url. This generally requires a hosted page somewhere that gets wrapped into the Electron window.

Intentionally Using the Firebase Node Bundles

If you intend to use Firebase’s Node bundles as Node bundles (for example, if it’s being imported and used in the Electron main process) then very little needs to be done other than:

  • If using Firestore, make sure gRPC is installed for Electron specifically and not just Node (see above).
  • Be aware of what Firebase APIs are not available in Node (Storage, Messaging, some Authentication methods involving redirects, popups, and recaptchas).

More Resources

For more info, check out Electron’s official docs on the difference between main and renderer processes.

--

--

Christina Holland
Firebase Developers

I’m not sure what kind of stuff I’m supposed to put on this website