Skip to content

Instantly share code, notes, and snippets.

@hirbod
Created May 1, 2025 19:02
Show Gist options
  • Save hirbod/23903dcca244bbca66ce0e3ba755e3a4 to your computer and use it in GitHub Desktop.
Save hirbod/23903dcca244bbca66ce0e3ba755e3a4 to your computer and use it in GitHub Desktop.
Expo SDK 53, New Arch, Metro Config with Crypto support
const { getSentryExpoConfig } = require('@sentry/react-native/metro')
const { withNativeWind } = require('nativewind/metro')
const path = require('path')
const config = getSentryExpoConfig(__dirname)
config.transformer.getTransformOptions = async () => ({
transform: {
experimentalImportSupport: true,
inlineRequires: true,
},
})
config.transformer = { ...config.transformer, unstable_allowRequireContext: true }
config.transformer.minifierPath = require.resolve('metro-minify-terser')
// Aliases for crypto
const nativeClientAliases = {
crypto: 'react-native-quick-crypto',
'node:crypto': 'react-native-quick-crypto',
stream: 'readable-stream',
'node:stream': 'readable-stream',
buffer: '@craftzdog/react-native-buffer',
'node:buffer': '@craftzdog/react-native-buffer',
}
/**
* Add the monorepo paths to the Metro config.
* This allows Metro to resolve modules from the monorepo.
*
* @see https://docs.expo.dev/guides/monorepos/#modify-the-metro-config
* @param {import('expo/metro-config').MetroConfig} config
* @returns {import('expo/metro-config').MetroConfig}
*/
function withMonorepoPaths(config) {
const projectRoot = __dirname
const workspaceRoot = path.resolve(projectRoot, '../..')
// #1 - Watch all files in the monorepo
config.watchFolders = [workspaceRoot]
// #2 - Resolve modules within the project's `node_modules` first, then all monorepo modules
config.resolver.nodeModulesPaths = [
path.resolve(projectRoot, 'node_modules'),
path.resolve(workspaceRoot, 'node_modules'),
]
return config
}
function withPackageExportsOrAliases(config) {
config.resolver.resolveRequest = (context, moduleName, platform) => {
// Alias crypto
const isServer = context.customResolverOptions?.environment === 'react-server'
const isApiRoute = context.customResolverOptions?.environment === 'node'
const isClient = !isServer && !isApiRoute
if (isClient) {
if (platform !== 'web') {
if (moduleName in nativeClientAliases) {
// when importing crypto, resolve to react-native-quick-crypto
return context.resolveRequest(context, nativeClientAliases[moduleName], platform)
}
}
if (moduleName === 'rpc-websockets' || moduleName === 'axios') {
// Since SDK 53, we need to fix some ESM problems with certain packages by adding the browser condition
// So far it's only been needed for rpc-websockets and axios
return context.resolveRequest(
{
...context,
unstable_conditionNames: ['browser'],
},
moduleName,
platform
)
}
}
// otherwise chain to the standard Metro resolver.
return context.resolveRequest(context, moduleName, platform)
}
// return the config
return config
}
module.exports = withNativeWind(withMonorepoPaths(withPackageExportsOrAliases(config)), {
input: './src/global.css',
inlineRem: 14,
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment