From 362723990545b7ba20196bd67a17783e343cacea Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Mon, 25 May 2026 19:21:59 +0300 Subject: [PATCH] 'fix' treeshaking for sentry --- eslint.config.mjs | 13 +++++++++++-- src/App.native.tsx | 2 +- src/App.web.tsx | 2 +- src/logger/reporting/sendErrorReport.ts | 2 +- src/logger/sentry/lib/index.ts | 14 +++++++++++++- src/logger/sentry/lib/index.web.ts | 1 - src/logger/transports/sentry.ts | 2 +- 7 files changed, 28 insertions(+), 8 deletions(-) delete mode 100644 src/logger/sentry/lib/index.web.ts diff --git a/eslint.config.mjs b/eslint.config.mjs index c2220134a4..cc846b4d5b 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -282,6 +282,11 @@ export default defineConfig( message: 'Import the helpers from #/lib/notifications/expo-helpers (or the hooks from #/lib/notifications/notifications) instead. expo-notifications is stubbed on web; importing it directly pulls ~70KB of dead weight into the web bundle.', }, + { + name: '@sentry/react-native', + message: + 'Import the curated Sentry barrel from #/logger/sentry/lib instead. Importing @sentry/react-native directly (especially as `import * as Sentry`) defeats Metro tree-shaking and pulls ~180KB of dead weight into the web bundle.', + }, ], }, ], @@ -318,14 +323,18 @@ export default defineConfig( }, /** - * Native-only files that legitimately wrap expo-notifications. The .web.ts - * counterparts to these files don't import the package. + * Files that legitimately wrap restricted packages (the no-restricted-imports + * rule above blocks `expo-notifications` and `@sentry/react-native` by + * default; these wrappers are how the rest of the codebase reaches them). */ { files: [ 'src/lib/notifications/notifications.ts', 'src/lib/notifications/expo-helpers.ts', 'src/lib/hooks/useNotificationHandler.ts', + 'src/logger/sentry/lib/index.ts', + 'src/logger/sentry/setup/index.ts', + 'src/logger/__tests__/logger.test.ts', ], rules: { 'no-restricted-imports': 'off', diff --git a/src/App.native.tsx b/src/App.native.tsx index 7bbe72a8d1..77156b9f4a 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -12,7 +12,6 @@ import * as ScreenOrientation from 'expo-screen-orientation' import * as SplashScreen from 'expo-splash-screen' import * as SystemUI from 'expo-system-ui' import {useLingui} from '@lingui/react/macro' -import * as Sentry from '@sentry/react-native' import {Provider as HideBottomBarBorderProvider} from '#/lib/hooks/useHideBottomBarBorder' import {QueryProvider} from '#/lib/react-query' @@ -20,6 +19,7 @@ import {ThemeProvider} from '#/lib/ThemeContext' import {Provider as TranslateOnDeviceProvider} from '#/lib/translation' import I18nProvider from '#/locale/i18nProvider' import {logger} from '#/logger' +import * as Sentry from '#/logger/sentry/lib' import {Provider as A11yProvider} from '#/state/a11y' import { prefetchAppConfig, diff --git a/src/App.web.tsx b/src/App.web.tsx index 178d3b8298..f542cd8369 100644 --- a/src/App.web.tsx +++ b/src/App.web.tsx @@ -6,7 +6,6 @@ import {Fragment, useEffect, useState} from 'react' import {KeyboardProvider as KeyboardControllerProvider} from 'react-native-keyboard-controller' import {SafeAreaProvider} from 'react-native-safe-area-context' import {useLingui} from '@lingui/react/macro' -import * as Sentry from '@sentry/react-native' import {Provider as HotkeysProvider} from '#/lib/hotkeys' import {QueryProvider} from '#/lib/react-query' @@ -14,6 +13,7 @@ import {ThemeProvider} from '#/lib/ThemeContext' import {Provider as TranslateOnDeviceProvider} from '#/lib/translation' import I18nProvider from '#/locale/i18nProvider' import {logger} from '#/logger' +import * as Sentry from '#/logger/sentry/lib' import {Provider as A11yProvider} from '#/state/a11y' import { prefetchAppConfig, diff --git a/src/logger/reporting/sendErrorReport.ts b/src/logger/reporting/sendErrorReport.ts index e0159c1703..c4b528eaf4 100644 --- a/src/logger/reporting/sendErrorReport.ts +++ b/src/logger/reporting/sendErrorReport.ts @@ -1,7 +1,7 @@ import slugify from 'slugify' import {getEntries} from '#/logger/logDump' -import {Sentry} from '#/logger/sentry/lib' +import * as Sentry from '#/logger/sentry/lib' export function sendErrorReport({ title, diff --git a/src/logger/sentry/lib/index.ts b/src/logger/sentry/lib/index.ts index e771560e73..865d7e91f2 100644 --- a/src/logger/sentry/lib/index.ts +++ b/src/logger/sentry/lib/index.ts @@ -1 +1,13 @@ -export * as Sentry from '@sentry/react-native' +// Curated re-export of @sentry/react-native. We list only the symbols the app +// actually uses, because `import * as Sentry from '@sentry/react-native'` +// defeats Metro's tree-shaker and pulls in ~180KB of dead weight. +// +// When adding a new function, add it here and run a web build to confirm +// tree-shaking is still working. +export { + addBreadcrumb, + captureException, + captureMessage, + withScope, + wrap, +} from '@sentry/react-native' diff --git a/src/logger/sentry/lib/index.web.ts b/src/logger/sentry/lib/index.web.ts deleted file mode 100644 index e771560e73..0000000000 --- a/src/logger/sentry/lib/index.web.ts +++ /dev/null @@ -1 +0,0 @@ -export * as Sentry from '@sentry/react-native' diff --git a/src/logger/transports/sentry.ts b/src/logger/transports/sentry.ts index 5453279015..0c734e1fbe 100644 --- a/src/logger/transports/sentry.ts +++ b/src/logger/transports/sentry.ts @@ -1,5 +1,5 @@ import {isNetworkError} from '#/lib/strings/errors' -import {Sentry} from '#/logger/sentry/lib' +import * as Sentry from '#/logger/sentry/lib' import {LogLevel, type Transport} from '#/logger/types' import {prepareMetadata} from '#/logger/util'