Skip to content

Commit 2179320

Browse files
authored
fix(telemetry): register React and ReactFire versions at import time (#835)
ReactFire registered the React and ReactFire versions with Firebase only when FirebaseAppProvider initialized a new app from firebaseConfig. Apps that passed firebaseApp, reused an initialized app, or called hooks without the provider reported no React or ReactFire version. src/telemetry.ts adds registerReactFireVersion, which registers both versions with registerVersion and runs at import time. FirebaseAppProvider (ahead of its early returns) and useObservable also call it as a fallback. Firebase's heartbeat records the registered versions once per UTC day, at the first _getProvider call (the first getFirestore(), getAuth(), and so on). Registering at import time therefore covers apps that create SDK instances at module scope, unless their entry file imports that setup before ReactFire. Those apps still go uncounted, so heartbeat counts are a lower bound. registerReactFireVersion checks Firebase's internal _components map before registering, so repeated calls do not log "There were multiple attempts to register component" at debug level. If that map is unavailable, a module-level flag prevents repeat calls instead. The function never throws, so a partially mocked or badly bundled firebase/app cannot break importing or rendering ReactFire.
1 parent 711828c commit 2179320

14 files changed

Lines changed: 226 additions & 30 deletions

‎docs/reference/functions/FirebaseAppProvider.md‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/reference/functions/preloadObservable.md‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/reference/functions/useFirebaseApp.md‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/reference/functions/useIsSuspenseEnabled.md‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/reference/functions/useObservable.md‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/reference/functions/useSuspenseEnabledFromConfigAndContext.md‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/reference/interfaces/FirebaseAppProviderProps.md‎

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/reference/interfaces/ObservableStatus.md‎

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/reference/variables/version.md‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/firebaseApp.tsx‎

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import * as React from 'react';
2-
import { getApps, initializeApp, registerVersion } from 'firebase/app';
2+
import { getApps, initializeApp } from 'firebase/app';
3+
import { registerReactFireVersion, version } from './telemetry.js';
34

45
import type { FirebaseApp, FirebaseOptions } from 'firebase/app';
56

6-
declare const process: { env: Record<string, string | undefined> };
7+
export { version };
78

89
// INVESTIGATE I don't like magic strings, can we have export this in js-sdk?
910
const DEFAULT_APP_NAME = '[DEFAULT]';
@@ -18,15 +19,14 @@ export interface FirebaseAppProviderProps {
1819
suspense?: boolean;
1920
}
2021

21-
// REACTFIRE_VERSION is automatically pulled in from `package.json` by Vite
22-
export const version = process.env.REACTFIRE_VERSION as string;
23-
2422
const shallowEq = (a: { [key: string]: any }, b: { [key: string]: any }) => a === b || [...Object.keys(a), ...Object.keys(b)].every((key) => a[key] === b[key]);
2523

2624
export function FirebaseAppProvider(props: React.PropsWithChildren<FirebaseAppProviderProps>) {
2725
const { firebaseConfig, appName, suspense } = props;
2826

2927
const firebaseApp: FirebaseApp = React.useMemo(() => {
28+
registerReactFireVersion();
29+
3030
if (props.firebaseApp) {
3131
return props.firebaseApp;
3232
}
@@ -45,9 +45,6 @@ export function FirebaseAppProvider(props: React.PropsWithChildren<FirebaseAppPr
4545
throw new Error('No firebaseConfig provided');
4646
}
4747

48-
const reactVersion = React.version || 'unknown';
49-
registerVersion('react', reactVersion);
50-
registerVersion('reactfire', version);
5148
return initializeApp(firebaseConfig, appName);
5249
}
5350
}, [props.firebaseApp, firebaseConfig, appName]);

0 commit comments

Comments
 (0)