You’ve asked for it, and now it’s here! We’re excited to announce that version 9 of the Firebase SDK is now generally available. This new version adopts a module first format that is optimized for elimination of unused code. The result is a potential significant reduction of Firebase library code in JavaScript bundles, up to 80% in some scenarios.
As of today running npm install firebase
will download the version 9 library. This new API is a major release and introduces several breaking changes. Upgrading to the new version can be done all at once or at your own pace with our compatibility library (more on that below). This post covers everything you need to know to get started. Check out our upgrade guide as well as our guide to using the new SDK with module bundlers for detailed guidance.
What’s new?
API changes for reduced size
Version 9 introduces a functional approach. In previous versions the API was organized into a traditional object-oriented structure. Using individual functions instead of structured objects allows JavaScript module bundlers such as webpack and Rollup to remove any unused code from the library. This is a concept known as tree shaking.
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); });
While this library organization is new, we have kept in place many familiar API concepts.
// 9.0.0
import { initializeApp } from 'firebase/app';
import { getAuth, onAuthStateChanged } from 'firebase/auth';
const firebaseApp = initializeApp({ /* config */ });
const auth = getAuth();
onAuthStateChanged(auth, user => { console.log(user); });
// 8.8.1
import firebase from 'firebase/app';
import 'firebase/auth';
const firebaseApp = firebase.initializeApp({ /* config */ });
const auth = firebaseApp.auth();
auth.onAuthStateChanged(user => { console.log(user); });
The sample above compares the same functionality, has the same amount of lines of code, and a similar API. The version 9 code however is 72% smaller than the version 8 example.
Keep in mind that while our functional approach is beneficial for tree shaking, this does not require you to write your code functionally. This new format provides an “import only what you need” approach. You can still structure your code in the ways that work best for you and your team.
import { getApp } from 'firebase/app';
import { getAuth, onAuthStateChanged } from 'firebase/auth';
class AuthService {
constructor(firebaseApp) {
this.auth = getAuth(firebaseApp);
}
waitForUser(callback) {
onAuthStateChanged(this.auth, user => {
if(user != null) { callback(user) }
});
}
}
const authService = new AuthService(getApp())
authService.waitForUser(user => { });
import { getApp } from 'firebase/app';
import { getAuth, onAuthStateChanged } from 'firebase/auth';
function waitForUser(auth, callback) {
onAuthStateChanged(auth, user => {
if(user != null) { callback(user) }
});
}
const auth = getAuth(getApp());
waitForUser(auth, user => { });
The samples above follow different structures. However, they have nearly the same bundle size. This is because they import the same pieces of functionality from the Firebase SDK.
A compatibility library for an easier upgrade
We understand that having to update code can be a lot of work. While your end users will experience real benefits in terms of bundle size and therefore page load performance, we want to make sure you can upgrade with minimal friction.
To simplify the upgrade process we have provided a compatibility library that ships with the version 9 npm package and is also available via a CDN script. To use the compatibility library via npm, you only need to update the import path.
import { initializeApp } from 'firebase/compat/app';
import 'firebase/compat/auth;
import { onAuthStateChanged } from 'firebase/auth';
const firebaseApp = firebase.initializeApp({ /* config */ });
const auth = firebaseApp.auth();
onAuthStateChanged(auth, user => { console.log(user); });
This library mirrors the version 8 API while using the version 9 library under-the-hood. It does not work with tree shaking, but it allows you to use the old and new APIs together. We refer to this as interop-mode.
Once your code is fully upgraded, you can remove the compatibility library and begin to see any potential tree shaking benefits.
Introducing Firestore Lite
We’re also excited to announce our newest library, Firestore Lite. Firestore Lite provides a REST based API for Firestore at a fraction of the bundle size. The library does not have support for realtime reads or any offline abilities. It is ideal for users who use Firestore for one-time reads.
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'));
Another benefit of Firestore Lite is that it can be used with the fully featured Firestore package. Some pages may only require single reads whereas some may need realtime streams. You have the option of using either (or both) in your web app where needed.
Moving away from the browser’s global window object
Another significant development in the new SDK is the move towards JavaScript modules (ESM) and away from the browser’s global window
object.
Historically libraries have been loaded and managed via a namespace on the window
, such as window.firebase
. This technique does not allow for tree shaking and lacks other benefits of the JavaScript module system.
This release prioritizes usage of Firebase via JavaScript modules. We still provide support for the window
via a CDN script for the compatibility library. However, we only recommend using it as a path to upgrading to the module based SDK.
Get started today
We are really excited about the new JavaScript SDK and we want to hear from you as well. We’ll be watching and responding to our GitHub discussion board for any questions or comments. If you’ve seen any size reductions in your codebase and want to share, let us know!