Description
1. Use case
An app that links only Analytics / Crashlytics / Messaging — and never links Firestore — still resolves and downloads the Firestore-only binary dependencies.
In our app the only linked Firebase products are FirebaseCore, FirebaseMessaging, FirebaseAnalytics and FirebaseCrashlytics. FirebaseFirestore is not linked anywhere. Despite that, SwiftPM downloads:
| Artifact |
Size |
grpc-binary 1.69.1 |
610 MB |
abseil-cpp-binary 1.2024072200.0 |
42 MB |
That is 652 MB, ~42% of our entire SwiftPM cache (1,543 MB total for all packages).
For comparison, the artifacts we actually use are much smaller: firebase-ios-sdk 132 MB and googleappmeasurement 42 MB.
2. How the Firebase SDK currently handles it
In Package.swift, gRPC and abseil are declared as package-level dependencies:
if shouldUseSourceFirestore {
packageInfo = ("https://github.com/grpc/grpc-ios.git", "1.69.0" ..< "1.70.0")
} else {
packageInfo = ("https://github.com/google/grpc-binary.git", "1.69.0" ..< "1.70.0")
}
and they are consumed only by the FirebaseFirestore target:
.product(name: "abseil", package: "abseil-cpp-binary", condition: .when(platforms: [...])),
.product(name: "gRPC-C++", package: "grpc-binary", condition: .when(platforms: [...])),
Because SwiftPM resolves and fetches binary artifacts for the whole package graph regardless of which products the app actually links, these binaries are downloaded by every app that depends on firebase-ios-sdk, including apps that never touch Firestore.
This is a regression in behaviour compared to CocoaPods, where only the pods matching the declared subspecs were installed.
3. How we propose the Firebase SDK should handle it
Make the Firestore-only binary dependencies conditional so that apps not linking FirebaseFirestore never resolve them. Two possible directions:
- Gate
grpc-binary / abseil-cpp-binary behind a SwiftPM trait, so they are only resolved when Firestore is requested; or
- Split Firestore (or at least its gRPC-dependent portion) into a separate package.
There is precedent for trimming the graph for exactly this reason: #15680 removed the swift-protobuf and GoogleDataTransport dependencies from ML Model Downloader to address #15649 ("Swift Package is very heavy"), shipped in 12.8.0. The Firestore binaries are more than an order of magnitude larger than what that PR saved.
Additional impact for Flutter apps
Flutter 3.44+ enables SwiftPM by default and points -clonedSourcePackagesDirPath at build/ios/SourcePackages, which flutter clean deletes. Every clean therefore discards these artifacts and the next build has to restore them. On CI, where each run starts from a cold cache, the 652 MB is downloaded on every single build.
Environment
- firebase-ios-sdk 12.15.0 (Swift Package Manager)
- grpc-binary 1.69.1, abseil-cpp-binary 1.2024072200.0
- Xcode 26.6 (17F113), macOS
- Flutter 3.44.9 (SwiftPM is the default since Flutter 3.44)
- Linked products: FirebaseCore, FirebaseMessaging, FirebaseAnalytics, FirebaseCrashlytics
- Not linked: FirebaseFirestore
Measured with du -sm build/ios/SourcePackages/artifacts/*:
610 artifacts/grpc-binary
132 artifacts/firebase-ios-sdk
42 artifacts/googleappmeasurement
42 artifacts/abseil-cpp-binary
14 artifacts/google-ads-on-device-conversion-ios-sdk
1543 (whole SourcePackages directory)
Firebase Product(s) dropdown: select Firestore (source of the dependency).
Others affected: Analytics, Crashlytics, Messaging.
API Proposal
No response
Firebase Product(s)
Firestore
Description
1. Use case
An app that links only Analytics / Crashlytics / Messaging — and never links Firestore — still resolves and downloads the Firestore-only binary dependencies.
In our app the only linked Firebase products are
FirebaseCore,FirebaseMessaging,FirebaseAnalyticsandFirebaseCrashlytics.FirebaseFirestoreis not linked anywhere. Despite that, SwiftPM downloads:grpc-binary1.69.1abseil-cpp-binary1.2024072200.0That is 652 MB, ~42% of our entire SwiftPM cache (1,543 MB total for all packages).
For comparison, the artifacts we actually use are much smaller:
firebase-ios-sdk132 MB andgoogleappmeasurement42 MB.2. How the Firebase SDK currently handles it
In
Package.swift, gRPC and abseil are declared as package-level dependencies:and they are consumed only by the
FirebaseFirestoretarget:Because SwiftPM resolves and fetches binary artifacts for the whole package graph regardless of which products the app actually links, these binaries are downloaded by every app that depends on
firebase-ios-sdk, including apps that never touch Firestore.This is a regression in behaviour compared to CocoaPods, where only the pods matching the declared subspecs were installed.
3. How we propose the Firebase SDK should handle it
Make the Firestore-only binary dependencies conditional so that apps not linking
FirebaseFirestorenever resolve them. Two possible directions:grpc-binary/abseil-cpp-binarybehind a SwiftPM trait, so they are only resolved when Firestore is requested; orThere is precedent for trimming the graph for exactly this reason: #15680 removed the
swift-protobufandGoogleDataTransportdependencies from ML Model Downloader to address #15649 ("Swift Package is very heavy"), shipped in 12.8.0. The Firestore binaries are more than an order of magnitude larger than what that PR saved.Additional impact for Flutter apps
Flutter 3.44+ enables SwiftPM by default and points
-clonedSourcePackagesDirPathatbuild/ios/SourcePackages, whichflutter cleandeletes. Every clean therefore discards these artifacts and the next build has to restore them. On CI, where each run starts from a cold cache, the 652 MB is downloaded on every single build.Environment
Measured with
du -sm build/ios/SourcePackages/artifacts/*:Firebase Product(s) dropdown: select Firestore (source of the dependency).
Others affected: Analytics, Crashlytics, Messaging.
API Proposal
No response
Firebase Product(s)
Firestore