firebase / firebase/firebase-ios-sdk
[FR]: SPM downloads gRPC/abseil binaries (652 MB) even when Firestore is not used
- Dominant language
- C++
- Stars
- 6.7k
- Forks
- 1.8k
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 75
Description
### 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:
```swift
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:
```swift
.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
Contributor guide
Assessment
This issue has not been assessed yet.