Introducing the new Firebase JS SDK

Get ready for a new faster web experience with Firebase. For the longest time you all have asked us to optimize the size of our JavaScript libraries, and we’ve done just that. We’ve released brand new beta libraries that are significantly smaller in size. Some are even up to 80% smaller! We’ve managed to reduce the size all without removing any features from the previous version too!

How did we do this? We did it by embracing the modern web and its new features. We converted our library to take advantage of code elimination features of modern day JavaScript tools like webpack and Rollup. While this change drops size, it did require us to change the library’s API for these tools to identify which functionality isn’t being used in your app.

This is a breaking change that will require you to update your code. We have released the library to npm under the beta tag, but we will be publishing it to the main tag in the near future. You can get started today and use the compatibility library to make the upgrade easier.

The new API

Let’s take a look at our new beta API.

Side-effect imports

The first thing you might notice is that we’ve removed all side-effect imports. You know, the import firebase/service lines of code, which aren’t very clear about what exactly is being imported. Or as webpack succinctly puts it

“A “side effect” is defined as code that performs a special behavior when imported, other than exposing one or more exports. An example of this are polyfills, which affect the global scope and usually do not provide an export.”

From now on in our API, we explicitly export each function from the package, which makes it clear what you are consuming in your app.

An illustration titled JavaScript Modules. No more side-effect imports. Directly import what you need. Followed by a code terminal with the code sample below.
An illustration titled JavaScript Modules. No more side-effect imports. Directly import what you need. Followed by a code terminal with the code sample below.
import { initializeApp } from 'firebase/app';
import { getAuth, onAuthStateChanged } from 'firebase/auth';

const firebaseApp = initializeApp({ /* config */ });
const auth = getAuth();
onAuthStateChanged(auth, user => { console.log(user); });

Individual entry points

This new API has a lot of familiar functions from the previous one. The main difference is the organization of the code. We’ve removed all side-effect imports and created individual entry points for each and every package.

An illustration titled Individual entry points. No more side-effect imports. Followed by a code terminal with the code sample below.
An illustration titled Individual entry points. No more side-effect imports. Followed by a code terminal with the code sample below.
import { initializeApp } from 'firebase/app';
import { getFirestore, collection, getDocs } from 'firebase/firestore';
import { getAuth, onAuthStateChanged } from 'firebase/auth';
import { getStorage, uploadBytes } from 'firebase/storage';
import { getRemoteConfig, fetchAndActivate } from 'firebase/remote-config';
import { getRemoteConfig, fetchAndActivate } from 'firebase/remote-config';
import { getDatabase, ref, get } from 'firebase/database';
import { getMessaging, getToken } from 'firebase/messaging';
import { getPerformance } from 'firebase/performance';
import { getAnalytics, logEvent } from 'firebase/analytics';

Tree-shaking with bundlers

Modern JavaScript tools like webpack and Rollup discourage the use of side-effect imports. This is because side-effect imports are like an unknown quantity. Module bundlers don’t know what they are going to bring in. Having explicit functions to import gives these tools a better understanding of how to build your code.

An illustration titled Optimized for tree-shaking. Dead code elimination with bundlers like webpack, Rollup, esbuild, Parcel. Followed by a code terminal with the code sample below.
An illustration titled Optimized for tree-shaking. Dead code elimination with bundlers like webpack, Rollup, esbuild, Parcel. Followed by a code terminal with the code sample below.
import { initializeApp } from 'firebase/app';
import { getAuth, onAuthStateChanged, getRedirectResult } from 'firebase/auth';

const firebaseApp = initializeApp({ /* config */ });
const auth = getAuth();
onAuthStateChanged(auth, user => {  console.log(user);});

When these tools can understand your code they can eliminate unused parts of a codebase, this is a feature called tree-shaking. This is what makes the new library so much smaller. By reorganizing the Firebase library we can take advantage of tree-shaking and remove all unneeded parts of the library from your app. This size savings we have seen have been significant.

How much smaller is the new library?

Let’s get real for a second and talk library size. Firebase has always been a larger library on the web. The web itself is a balance of features and performance and we wanted to make that balance a lot easier for you. This was the biggest reason for us to take on tree shaking. We suspect that no matter what you’ll see a sizable drop in your bundle size. However, we’re hoping that with specific use cases you’ll see significant size reductions.

The two biggest areas of improvement we have seen in our early studies are with the new firebase/firestore/lite package (more on that in a bit!) and firebase/auth. The table below shows a package, the current SDK version size, the current beta version size for a basic use case, and the percentage the SDK is lighter than the current v8 version.

An illustration titled A smaller Firebase. 8.7.1 vs 9.0.0-beta.6. Followed by a code terminal with the code sample below.
An illustration titled A smaller Firebase. 8.7.1 vs 9.0.0-beta.6. Followed by a code terminal with the code sample below.

You’ll notice that authentication can be up to 72% lighter than before. When using firebase/firestore/lite you can save 84% from the current version of firebase/firestore if you only need one-time reads. This new “import only what you need” method allows you to decide what to include in your bundles and make that features and performance balance much easier.

Introducing Firestore Lite

Firestore is such a powerful library because it does so many things behind the scenes that we encourage you all to take for granted. Firestore has a complex caching, realtime streaming, persistent storage, multi-tab offline sync, retries, optimistic concurrency, and so much more. But we heard from you all that sometimes you just need to get a collection, and don’t want to include all of Firestore’s other features in your site. For those cases we wanted to make Firestore a simple and light solution, so we created a brand new subpackage: firebase/firestore/lite.

An illustration titled Firestore Lite. A small, REST-based client library. Followed by a code terminal with the code sample below.
An illustration titled Firestore Lite. A small, REST-based client library. Followed by a code terminal with the code sample below.
import { initializeApp } from 'firebase/app';
import { getFirestore, collection, getDocs } from 'firebase/firestore/lite';

const firebaseApp = initializeApp({ /* config */ });
const db = getFirestore();
const snapshot = await getDocs(collection('cities'));

A lightweight, REST based, API

This sample uses firebase/app and the new firebase/firestore/lite package. You’ll notice that calling getDocs() initiates a one-time data read. Firestore Lite allows you to create, read, update, and delete data with Firestore in a much smaller library. Realtime streaming is not included, but you can always switch back to firebase/firestore if that’s what you need. If you want to adopt an advanced loading strategy, you can even load firestore/lite for a fast initial page load and lazy load firebase/firestore for progressive enhancement.

Firestore Lite is significantly smaller. As you saw in the table above, it can be 84% lighter. We know that you Firestore users will find a great fit for this library.

An easier upgrade with our compatibility library

Change is never easy. Our new library provides new benefits but it’s hard to go back and rewrite code that already works. To make that process easier, we’re also releasing a compatibility library that allows you to port your code piece by piece.

An illustration titled Upgrade easily with compat. Import firebase/compat/service. Followed by a code terminal with the code sample below.
An illustration titled Upgrade easily with compat. Import firebase/compat/service. Followed by a code terminal with the code sample below.
import { initializeApp } from 'firebase/compat/app';
import 'firebase/auth/compat';
import { onAuthStateChanged } from 'firebase/auth';

const firebaseApp = firebase.initializeApp({ /* config */ });
const auth = firebaseApp.auth();
onAuthStateChanged(auth, user => { console.log(user); });

The new modular SDK cannot be used alongside the existing namespace based library, but the compatibility library allows you to use both APIs at the same time. You won’t get all of the tree shaking advantages upfront, but once you match the new modular library you can switch off the compatibility library and rake in the savings.

What about framework integrations?

Libraries like AngularFire, ReactFire, and RxFire will be compatible with the new SDK in the near future. We are close to completing them, so hang tight! Track their progress in these issues on GitHub.

Once they have been updated there will be little to no work to move over, as we will update them underneath the hood. However, AngularFire will not initially receive all of the tree shaking benefits since it follows a classical OOP structure. We plan on releasing an API proposal in the near future to optimize for tree shaking and provide an easy path to upgrade as well.

Get started today

The new JavaScript library is available today on npm under the beta tag. We want to hear your feedback! Tell us what you think of the new API and any size savings you’ve seen. We’re excited about the future of this library and the performance benefits it brings.

An illustration titled Get started today. firebase@beta. Followed by a code terminal with the code sample below.
An illustration titled Get started today. firebase@beta. Followed by a code terminal with the code sample below.

To learn more about the new library, see our talk at Google I/O. Also check out our upgrade guide for in-depth information about the upgrade process.