Files
a9622664e2 fix(mobile): shim ws to empty in Metro production builds
viem's barrel export statically imports isows → ws, which requires
Node.js built-ins (stream, http, events). In dev mode Metro resolves
lazily so this is never hit, but production builds eagerly resolve
all static imports and fail. Since React Native provides a native
WebSocket global (isows uses it, never falling back to ws), shimming
ws to empty is safe.

Co-authored-by: Hanzo Dev <[email protected]>
2026-04-28 10:29:13 +02:00

34 lines
1.2 KiB
JavaScript

const path = require('path')
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDatadogExpoConfig } = require('@datadog/mobile-react-native/metro')
const { withStorybook } = require('@storybook/react-native/metro/withStorybook')
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDatadogExpoConfig(__dirname)
config.resolver.resolveRequest = (context, moduleName, platform) => {
if (moduleName === 'crypto') {
// when importing crypto, resolve to react-native-quick-crypto
return context.resolveRequest(context, 'react-native-quick-crypto', platform)
}
// viem's barrel export pulls in ws (Node.js WebSocket server) which requires
// http, stream, events, etc. On React Native, isows uses the native WebSocket
// global instead, so ws never executes. Shim the entire ws package to empty.
if (moduleName === 'ws') {
return { type: 'empty' }
}
return context.resolveRequest(context, moduleName, platform)
}
if (process.env.RN_SRC_EXT) {
config.resolver.sourceExts = [...process.env.RN_SRC_EXT.split(','), ...config.resolver.sourceExts]
}
module.exports = withStorybook(config, {
enabled: process.env.STORYBOOK_ENABLED === 'true',
configPath: path.resolve(__dirname, './.storybook'),
})