Skip to content

Production build exclusions ​

When APP_VARIANT=production, Metro's resolver strips several categories of code and assets from the JS bundle by resolving them to empty modules. This keeps production bundles lean and free of dev-only code.

All of this logic lives in metro.config.js under resolveRequest.

What gets excluded ​

ExclusionPath matchPurpose
Storybook.rnstorybook/Component stories and Storybook UI. Also handled by the withStorybook wrapper with onDisabledRemoveStorybook: true
Non-prod code/__non-prod__/Debug panels, dev menus, and their utilities
Imported assetssrc/design-system/styling/imported-assetsDesign token assets not needed at runtime
Boxt stylesimported-styles/boxtLegacy Boxt-specific style imports
Other clients' build assetsbuild-assets/<not-current-client>/Icons, splash screens, etc. for other white-label clients
Other clients' assetsassets/clients/<not-current-client>/Client-specific assets for other white-label clients

The current client is determined from env-config.json's NAME field (lowercased).

The __non-prod__ convention ​

Any folder named __non-prod__ is stripped from production builds. This is the convention for debug-only code.

Current directories ​

src/components/__non-prod__/                            # Debug panel (floating dev overlay)
src/components/drawers/DrawerContent/__non-prod__/      # Debug menu drawer screens
src/utils/__non-prod__/                                 # Hooks/utilities used only by debug code

Adding new debug-only code ​

  1. Place the code inside a __non-prod__ folder (existing or new)
  2. Import it with a conditional require guarded by env.IS_PRODUCTION:
typescript
import env from 'src/env';

let MyDevTool;

if (!env.IS_PRODUCTION) {
  MyDevTool = require('src/components/__non-prod__/MyDevTool').default;
}

The env.IS_PRODUCTION guard prevents the require from executing at runtime, and Metro's resolver prevents the module from being included in the bundle.

WARNING

Don't use a static import for __non-prod__ modules. Static imports can't be conditionally skipped, so Metro would still try to resolve the module — and in production it resolves to empty, which breaks the import.