Skip to content

Commit 34e89a4

Browse files
fix: Bundle includes unused firebase modules (#3366)
* fix: Bundle includes unused firebase modules `@angular/fire` core package always import these packages - firebase/remote-config - firebase/messaging - firebase/analytics which increase the total bundle size for any application using `@angular/fire` Fix #3075 * Update src/remote-config/is-remote-config-supported-factory.ts * Update src/messaging/is-messaging-supported-factory.ts * Update src/analytics/is-analytics-supported-factory.ts --------- Co-authored-by: David East <[email protected]>
1 parent a26980b commit 34e89a4

10 files changed

+82
-74
lines changed

src/analytics/analytics.module.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
import { NgModule, Optional, NgZone, InjectionToken, ModuleWithProviders, APP_INITIALIZER, Injector } from '@angular/core';
22
import { Analytics as FirebaseAnalytics } from 'firebase/analytics';
3-
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION, ɵisAnalyticsSupportedFactory } from '@angular/fire';
3+
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION } from '@angular/fire';
44
import { Analytics, ANALYTICS_PROVIDER_NAME, AnalyticsInstances } from './analytics';
55
import { FirebaseApps, FirebaseApp } from '@angular/fire/app';
66
import { registerVersion } from 'firebase/app';
77
import { ScreenTrackingService } from './screen-tracking.service';
88
import { UserTrackingService } from './user-tracking.service';
9+
import { isAnalyticsSupportedFactory } from './is-analytics-supported-factory';
910

1011
export const PROVIDED_ANALYTICS_INSTANCES = new InjectionToken<Analytics[]>('angularfire2.analytics-instances');
1112

1213
export function defaultAnalyticsInstanceFactory(provided: FirebaseAnalytics[]|undefined, defaultApp: FirebaseApp) {
13-
if (!ɵisAnalyticsSupportedFactory.sync()) { return null; }
14+
if (!isAnalyticsSupportedFactory.sync()) { return null; }
1415
const defaultAnalytics = ɵgetDefaultInstanceOf<FirebaseAnalytics>(ANALYTICS_PROVIDER_NAME, provided, defaultApp);
1516
return defaultAnalytics && new Analytics(defaultAnalytics);
1617
}
1718

1819
export function analyticsInstanceFactory(fn: (injector: Injector) => FirebaseAnalytics) {
1920
return (zone: NgZone, injector: Injector) => {
20-
if (!ɵisAnalyticsSupportedFactory.sync()) { return null; }
21+
if (!isAnalyticsSupportedFactory.sync()) { return null; }
2122
const analytics = zone.runOutsideAngular(() => fn(injector));
2223
return new Analytics(analytics);
2324
};
@@ -45,7 +46,7 @@ const DEFAULT_ANALYTICS_INSTANCE_PROVIDER = {
4546
ANALYTICS_INSTANCES_PROVIDER,
4647
{
4748
provide: APP_INITIALIZER,
48-
useValue: ɵisAnalyticsSupportedFactory.async,
49+
useValue: isAnalyticsSupportedFactory.async,
4950
multi: true,
5051
}
5152
]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { ɵisSupportedError } from '@angular/fire';
2+
import { isSupported } from 'firebase/analytics';
3+
4+
const isAnalyticsSupportedValueSymbol = '__angularfire_symbol__analyticsIsSupportedValue';
5+
const isAnalyticsSupportedPromiseSymbol = '__angularfire_symbol__analyticsIsSupported';
6+
7+
globalThis[isAnalyticsSupportedPromiseSymbol] ||= isSupported().then(it =>
8+
globalThis[isAnalyticsSupportedValueSymbol] = it
9+
).catch(() =>
10+
globalThis[isAnalyticsSupportedValueSymbol] = false
11+
);
12+
export const isAnalyticsSupportedFactory = {
13+
async: () => globalThis[isAnalyticsSupportedPromiseSymbol],
14+
sync: () => {
15+
const ret = globalThis[isAnalyticsSupportedValueSymbol];
16+
if (ret === undefined) { throw new Error(ɵisSupportedError('Analytics')); }
17+
return ret;
18+
}
19+
};

src/analytics/overrides.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
import { ɵisAnalyticsSupportedFactory } from '@angular/fire';
1+
import { isAnalyticsSupportedFactory } from './is-analytics-supported-factory';
2+
3+
export const isSupported = isAnalyticsSupportedFactory.async;
24

3-
export const isSupported = ɵisAnalyticsSupportedFactory.async;

src/core.ts

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,14 @@
11
import { Version } from '@angular/core';
22
import { FirebaseApp, getApps } from 'firebase/app';
33
import { ComponentContainer } from '@firebase/component';
4-
import { isSupported as isRemoteConfigSupported } from 'firebase/remote-config';
5-
import { isSupported as isMessagingSupported } from 'firebase/messaging';
6-
import { isSupported as isAnalyticsSupported } from 'firebase/analytics';
74

85
export const VERSION = new Version('ANGULARFIRE2_VERSION');
96

10-
const isAnalyticsSupportedValueSymbol = '__angularfire_symbol__analyticsIsSupportedValue';
11-
const isAnalyticsSupportedPromiseSymbol = '__angularfire_symbol__analyticsIsSupported';
12-
const isRemoteConfigSupportedValueSymbol = '__angularfire_symbol__remoteConfigIsSupportedValue';
13-
const isRemoteConfigSupportedPromiseSymbol = '__angularfire_symbol__remoteConfigIsSupported';
14-
const isMessagingSupportedValueSymbol = '__angularfire_symbol__messagingIsSupportedValue';
15-
const isMessagingSupportedPromiseSymbol = '__angularfire_symbol__messagingIsSupported';
16-
17-
globalThis[isAnalyticsSupportedPromiseSymbol] ||= isAnalyticsSupported().then(it =>
18-
globalThis[isAnalyticsSupportedValueSymbol] = it
19-
).catch(() =>
20-
globalThis[isAnalyticsSupportedValueSymbol] = false
21-
);
22-
23-
globalThis[isMessagingSupportedPromiseSymbol] ||= isMessagingSupported().then(it =>
24-
globalThis[isMessagingSupportedValueSymbol] = it
25-
).catch(() =>
26-
globalThis[isMessagingSupportedValueSymbol] = false
27-
);
28-
29-
globalThis[isRemoteConfigSupportedPromiseSymbol] ||= isRemoteConfigSupported().then(it =>
30-
globalThis[isRemoteConfigSupportedValueSymbol] = it
31-
).catch(() =>
32-
globalThis[isRemoteConfigSupportedValueSymbol] = false
33-
);
34-
35-
const isSupportedError = (module: string) =>
7+
export const ɵisSupportedError = (module: string) =>
368
`The APP_INITIALIZER that is "making" isSupported() sync for the sake of convenient DI has not resolved in this
379
context. Rather than injecting ${module} in the constructor, first ensure that ${module} is supported by calling
3810
\`await isSupported()\`, then retrieve the instance from the injector manually \`injector.get(${module})\`.`;
3911

40-
export const ɵisMessagingSupportedFactory = {
41-
async: () => globalThis[isMessagingSupportedPromiseSymbol],
42-
sync: () => {
43-
const ret = globalThis[isMessagingSupportedValueSymbol];
44-
if (ret === undefined) { throw new Error(isSupportedError('Messaging')); }
45-
return ret;
46-
}
47-
};
48-
49-
export const ɵisRemoteConfigSupportedFactory = {
50-
async: () => globalThis[isRemoteConfigSupportedPromiseSymbol],
51-
sync: () => {
52-
const ret = globalThis[isRemoteConfigSupportedValueSymbol];
53-
if (ret === undefined) { throw new Error(isSupportedError('RemoteConfig')); }
54-
return ret;
55-
}
56-
};
57-
58-
export const ɵisAnalyticsSupportedFactory = {
59-
async: () => globalThis[isAnalyticsSupportedPromiseSymbol],
60-
sync: () => {
61-
const ret = globalThis[isAnalyticsSupportedValueSymbol];
62-
if (ret === undefined) { throw new Error(isSupportedError('Analytics')); }
63-
return ret;
64-
}
65-
};
66-
6712
// TODO is there a better way to get at the internal types?
6813
interface FirebaseAppWithContainer extends FirebaseApp {
6914
container: ComponentContainer;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { ɵisSupportedError } from '@angular/fire';
2+
import { isSupported } from 'firebase/messaging';
3+
4+
const isMessagingSupportedPromiseSymbol = '__angularfire_symbol__messagingIsSupported';
5+
const isMessagingSupportedValueSymbol = '__angularfire_symbol__messagingIsSupportedValue';
6+
7+
globalThis[isMessagingSupportedPromiseSymbol] ||= isSupported().then(it =>
8+
globalThis[isMessagingSupportedValueSymbol] = it
9+
).catch(() =>
10+
globalThis[isMessagingSupportedValueSymbol] = false
11+
);
12+
13+
export const isMessagingSupportedFactory = {
14+
async: () => globalThis[isMessagingSupportedPromiseSymbol],
15+
sync: () => {
16+
const ret = globalThis[isMessagingSupportedValueSymbol];
17+
if (ret === undefined) { throw new Error(ɵisSupportedError('Messaging')); }
18+
return ret;
19+
}
20+
};

src/messaging/messaging.module.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
import { NgModule, Optional, NgZone, InjectionToken, ModuleWithProviders, Injector, APP_INITIALIZER } from '@angular/core';
22
import { Messaging as FirebaseMessaging } from 'firebase/messaging';
3-
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION, ɵisMessagingSupportedFactory } from '@angular/fire';
3+
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION } from '@angular/fire';
44
import { Messaging, MessagingInstances, MESSAGING_PROVIDER_NAME } from './messaging';
55
import { FirebaseApps, FirebaseApp } from '@angular/fire/app';
66
import { registerVersion } from 'firebase/app';
7+
import { isMessagingSupportedFactory } from './is-messaging-supported-factory';
78

89
const PROVIDED_MESSAGING_INSTANCES = new InjectionToken<Messaging[]>('angularfire2.messaging-instances');
910

1011
export function defaultMessagingInstanceFactory(provided: FirebaseMessaging[]|undefined, defaultApp: FirebaseApp) {
11-
if (!ɵisMessagingSupportedFactory.sync()) { return null; }
12+
if (!isMessagingSupportedFactory.sync()) { return null; }
1213
const defaultMessaging = ɵgetDefaultInstanceOf<FirebaseMessaging>(MESSAGING_PROVIDER_NAME, provided, defaultApp);
1314
return defaultMessaging && new Messaging(defaultMessaging);
1415
}
1516

1617
export function messagingInstanceFactory(fn: (injector: Injector) => FirebaseMessaging) {
1718
return (zone: NgZone, injector: Injector) => {
18-
if (!ɵisMessagingSupportedFactory.sync()) { return null; }
19+
if (!isMessagingSupportedFactory.sync()) { return null; }
1920
const messaging = zone.runOutsideAngular(() => fn(injector));
2021
return new Messaging(messaging);
2122
};
@@ -43,7 +44,7 @@ const DEFAULT_MESSAGING_INSTANCE_PROVIDER = {
4344
MESSAGING_INSTANCES_PROVIDER,
4445
{
4546
provide: APP_INITIALIZER,
46-
useValue: ɵisMessagingSupportedFactory.async,
47+
useValue: isMessagingSupportedFactory.async,
4748
multi: true,
4849
},
4950
]

src/messaging/overrides.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import { ɵisMessagingSupportedFactory } from '@angular/fire';
1+
import { isMessagingSupportedFactory } from './is-messaging-supported-factory';
22

3-
export const isSupported = ɵisMessagingSupportedFactory.async;
3+
export const isSupported = isMessagingSupportedFactory.async;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { isSupported } from 'firebase/remote-config';
2+
import { ɵisSupportedError } from '@angular/fire';
3+
4+
const isRemoteConfigSupportedValueSymbol = '__angularfire_symbol__remoteConfigIsSupportedValue';
5+
const isRemoteConfigSupportedPromiseSymbol = '__angularfire_symbol__remoteConfigIsSupported';
6+
7+
globalThis[isRemoteConfigSupportedPromiseSymbol] ||= isSupported().then(it =>
8+
globalThis[isRemoteConfigSupportedValueSymbol] = it
9+
).catch(() =>
10+
globalThis[isRemoteConfigSupportedValueSymbol] = false
11+
);
12+
13+
export const isRemoteConfigSupportedFactory = {
14+
async: () => globalThis[isRemoteConfigSupportedPromiseSymbol],
15+
sync: () => {
16+
const ret = globalThis[isRemoteConfigSupportedValueSymbol];
17+
if (ret === undefined) { throw new Error(ɵisSupportedError('RemoteConfig')); }
18+
return ret;
19+
}
20+
};

src/remote-config/overrides.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import { ɵisRemoteConfigSupportedFactory } from '@angular/fire';
1+
import { isRemoteConfigSupportedFactory } from './is-remote-config-supported-factory';
22

3-
export const isSupported = ɵisRemoteConfigSupportedFactory.async;
3+
export const isSupported = isRemoteConfigSupportedFactory.async;

src/remote-config/remote-config.module.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
import { NgModule, Optional, NgZone, InjectionToken, ModuleWithProviders, Injector, APP_INITIALIZER } from '@angular/core';
22
import { RemoteConfig as FirebaseRemoteConfig } from 'firebase/remote-config';
3-
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION, ɵisRemoteConfigSupportedFactory } from '@angular/fire';
3+
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION } from '@angular/fire';
44
import { RemoteConfig, RemoteConfigInstances, REMOTE_CONFIG_PROVIDER_NAME } from './remote-config';
55
import { FirebaseApps, FirebaseApp } from '@angular/fire/app';
66
import { registerVersion } from 'firebase/app';
7+
import { isRemoteConfigSupportedFactory } from './is-remote-config-supported-factory';
78

89
export const PROVIDED_REMOTE_CONFIG_INSTANCES = new InjectionToken<RemoteConfig[]>('angularfire2.remote-config-instances');
910

1011
export function defaultRemoteConfigInstanceFactory(
1112
provided: FirebaseRemoteConfig[]|undefined,
1213
defaultApp: FirebaseApp,
1314
) {
14-
if (!ɵisRemoteConfigSupportedFactory.sync()) { return null; }
15+
if (!isRemoteConfigSupportedFactory.sync()) { return null; }
1516
const defaultRemoteConfig = ɵgetDefaultInstanceOf<FirebaseRemoteConfig>(REMOTE_CONFIG_PROVIDER_NAME, provided, defaultApp);
1617
return defaultRemoteConfig && new RemoteConfig(defaultRemoteConfig);
1718
}
1819

1920
export function remoteConfigInstanceFactory(fn: (injector: Injector) => FirebaseRemoteConfig) {
2021
return (zone: NgZone, injector: Injector) => {
21-
if (!ɵisRemoteConfigSupportedFactory.sync()) { return null; }
22+
if (!isRemoteConfigSupportedFactory.sync()) { return null; }
2223
const remoteConfig = zone.runOutsideAngular(() => fn(injector));
2324
return new RemoteConfig(remoteConfig);
2425
};
@@ -46,7 +47,7 @@ const DEFAULT_REMOTE_CONFIG_INSTANCE_PROVIDER = {
4647
REMOTE_CONFIG_INSTANCES_PROVIDER,
4748
{
4849
provide: APP_INITIALIZER,
49-
useValue: ɵisRemoteConfigSupportedFactory.async,
50+
useValue: isRemoteConfigSupportedFactory.async,
5051
multi: true,
5152
},
5253
]

0 commit comments

Comments
 (0)