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 ​
| Exclusion | Path match | Purpose |
|---|---|---|
| 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 assets | src/design-system/styling/imported-assets | Design token assets not needed at runtime |
| Boxt styles | imported-styles/boxt | Legacy Boxt-specific style imports |
| Other clients' build assets | build-assets/<not-current-client>/ | Icons, splash screens, etc. for other white-label clients |
| Other clients' assets | assets/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 codeAdding new debug-only code ​
- Place the code inside a
__non-prod__folder (existing or new) - Import it with a conditional
requireguarded byenv.IS_PRODUCTION:
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.