Files
orca/mobile/metro.config.js
T
Jinwoo Hong b76bc79d73 build(mobile): key Metro's transform cache on the shell build kind (#22244)
`babel-preset-expo` inlines `EXPO_PUBLIC_MOBILE_SHELL` into
`mobileShellBuildKind` at transform time
(babel-preset-expo/build/inline-env-vars.js:51), but nothing Metro hashes
into the transform cache key carries that value: the key is
`metro/src/DeltaBundler/getTransformCacheKey.js:21`, whose inputs are the
Metro version, `cacheVersion`, the transformer path and
`@expo/metro-config/build/transform-worker/metro-transform-worker.js:600`,
none of which reads the environment. A release assembled after an
opposite-kind build reuses the warm entries and bakes the wrong shell,
and the absence of the variable's name in the bundle cannot tell the two
apart. The newest published `@expo/metro-config` (58.0.4) keys it no
differently.

Folds the kind into `cacheVersion`, by the same `=== 'ota'` rule the app
applies, keeping Metro's own version as the prefix.

Proven with four `expo export --platform android` runs against an
isolated Metro cache. Before: `ota` then `native` produced byte-identical
bundles, both `return 'ota'`. After: the second run returns `'native'`
under a different bundle hash.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-22 07:57:43 -04:00

26 lines
1.1 KiB
JavaScript

const path = require('node:path')
const { getDefaultConfig } = require('expo/metro-config')
const projectRoot = __dirname
const sharedRoot = path.resolve(projectRoot, '..', 'src', 'shared')
const config = getDefaultConfig(projectRoot)
// Why: mobile source-control prompts use the same pure builders as desktop.
// Metro only watches mobile/ by default, so make repo-root shared modules visible.
config.watchFolders = Array.from(new Set([...(config.watchFolders ?? []), sharedRoot]))
/**
* The shell kind the bundle is being built for, by the same rule `mobileShellBuildKind` applies in
* `src/storage/preferences.ts`. This read runs in Node at config time, so it is not the second
* inlined read that module's census forbids.
*/
const shellBuildKind = process.env.EXPO_PUBLIC_MOBILE_SHELL === 'ota' ? 'ota' : 'native'
// Why: babel-preset-expo inlines EXPO_PUBLIC_MOBILE_SHELL at transform time, but nothing Metro
// hashes into the transform cache key carries that value, so a warm cache from the opposite kind
// silently bakes the wrong shell into a release.
config.cacheVersion = `${config.cacheVersion}-shell-${shellBuildKind}`
module.exports = config