Bundle includes unused firebase modules with the new angularfire API
Version info
Angular: 13.0.0
Firebase: 9.4.1
AngularFire: 7.2.0
How to reproduce these conditions
I'm using the new angular fire API and I see great improvements in comparison with the old compat api regarding bundle size. Nevertheless I still see in the final bundle that it includes some things (like analytics, app-check, messaging) that I'm not using.
These functions are never imported in the code, and my firebase module looks like this:
import { NgModule } from '@angular/core';
import { environment } from 'src/environments/environment';
import { getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app';
import {
provideAuth, initializeAuth, browserPopupRedirectResolver,
indexedDBLocalPersistence
} from '@angular/fire/auth';
import { getFirestore, provideFirestore } from '@angular/fire/firestore';
import { getFunctions, provideFunctions } from '@angular/fire/functions';
import { getStorage, provideStorage } from '@angular/fire/storage';
import {
connectAuthEmulatorInDevMode,
connectFirestoreEmulatorInDevMode,
connectFunctionsEmulatorInDevMode,
connectStorageEmulatorInDevMode
} from './emulators';
@NgModule({
imports: [
provideFirebaseApp(() => initializeApp(environment.firebase)),
provideFirestore(() => {
const firestore = getFirestore();
if (environment.firebase.localEmulator) {
connectFirestoreEmulatorInDevMode(firestore);
}
return firestore;
}),
provideFunctions(() => {
const functions = getFunctions();
if (environment.firebase.localEmulator) {
connectFunctionsEmulatorInDevMode(functions);
}
return functions;
}),
]
})
export class FirebaseModule {}
@NgModule({
imports: [
provideStorage(() => {
const storage = getStorage();
if (environment.firebase.localEmulator) {
connectStorageEmulatorInDevMode(storage);
}
return storage;
}),
provideAuth(() => {
const auth = initializeAuth(getApp(), {
persistence: indexedDBLocalPersistence,
popupRedirectResolver: browserPopupRedirectResolver,
});
if (environment.firebase.localEmulator) {
connectAuthEmulatorInDevMode(auth);
}
return auth;
})
]
})
export class FirebaseBrowserModule {}
As I'm using only storage, firestore, functions, and auth, I would expect to only see that in the generated bundle:

It seems that the other modules are being included.
Is this the expected behavior? I thought that the new structure allowed to actually prevent this.
Also, is that a normal firestore bundle size? I'm using only these:
import {
collection, doc, docData, Firestore, query, collectionSnapshots,
DocumentSnapshot, QueryDocumentSnapshot, DocumentData, updateDoc, setDoc,
DocumentReference, UpdateData, addDoc, deleteDoc, QueryConstraint
} from '@angular/fire/firestore';
For reference I include here the same app, but with the compat API:

So the improvement is already quite good, from 167 KB to 113 KB. I hope there is still room for improvement.
Are you building for production? E.g, tree-shaking? Otherwise unnecessary modules will not be stripped
Yes I think I am. This is the command I'm using to build:
ng build --configuration=production --source-map --named-chunks=true
And this is the production configuration in my angular.js:
"production": {
"deleteOutputPath": false,
"aot": true,
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "7kb"
}
],
"serviceWorker": true,
"ngswConfigPath": "ngsw-config.json",
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
},
{
"replace": "src/app/modules/firebase/emulators.ts",
"with": "src/app/modules/firebase/emulators.prod.ts"
}
]
}
Am I missing some option?
Hey, were you able to figure the issue?
I am using "firebase": "9.15.0" and "@angular/fire": "7.5.0" with 100% modular imports (no compat imports left), via a standalone component (killed all modules in favor of standalone). I can observe the same problem: my prod build still contains messaging, remote config, app-check, which are never used anywhere in my app.
Any updates? Same problem here.
in https://github.com/angular/angularfire/blob/master/src/core.ts#L4
import { isSupported as isRemoteConfigSupported } from 'firebase/remote-config';
import { isSupported as isMessagingSupported } from 'firebase/messaging';
import { isSupported as isAnalyticsSupported } from 'firebase/analytics';
this is the root cause of the problem and since this is in the core package, importing anything will lead to importing 50 KB of totally unused code
@davideast for the app-check the problem is in this kind of import inside almost every module
https://github.com/angular/angularfire/blob/master/src/auth/auth.module.ts#L63
is there a way to fix it?
I'm thinking to move it to core, and use it from core everywhere