react-native-community / upgrade-support

A central community-backed place to request and give help when upgrading your app.
MIT License
251 stars 2 forks source link

Metro configuration changes in 0.72 breaking app #277

Open bhandanyan-nomad opened 1 month ago

bhandanyan-nomad commented 1 month ago

Environment

System:
  OS: macOS 14.0
  CPU: (12) arm64 Apple M2 Pro
  Memory: 724.58 MB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 20.10.0
    path: ~/.nvm/versions/node/v20.10.0/bin/node
  Yarn:
    version: 1.22.19
    path: /opt/homebrew/bin/yarn
  npm:
    version: 10.2.3
    path: ~/.nvm/versions/node/v20.10.0/bin/npm
  Watchman:
    version: 2024.05.06.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /Users/benjamin/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.5
      - iOS 17.5
      - macOS 14.5
      - tvOS 17.5
      - visionOS 1.2
      - watchOS 10.5
  Android SDK: Not Found
IDEs:
  Android Studio: 2022.2 AI-222.4459.24.2221.9971841
  Xcode:
    version: 15.4/15F31d
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 11.0.19
    path: /usr/bin/javac
  Ruby:
    version: 3.3.0
    path: /Users/benjamin/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.72.14
    wanted: 0.72.14
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

Things I’ve done to figure out my issue

Upgrading version

0.72.14

Description

Upon upgrading to 0.72+, my app stops working. It still builds and runs, but certain features are fatally broken. The main things that are broken are:

So far I've narrowed down my issue to the metro configuration. As soon as I merge my configuration with the new defaultConfiguration the app breaks as described. If I revert back to my old configuration, it works on iOS (but Android fails to build).

Working config:

{
  transformer: {
    babelTransformerPath: '/Users/benjamin/repos/nomad-react-native/node_modules/react-native-svg-transformer/index.js',
    minifierConfig: { keep_classnames: true, keep_fnames: true, mangle: [Object] }
  },
  maxWorkers: 2,
  resolver: {
    assetExts: [
      'bmp',  'gif',  'jpg',  'jpeg',
      'png',  'psd',  'webp', 'm4v',
      'mov',  'mp4',  'mpeg', 'mpg',
      'webm', 'aac',  'aiff', 'caf',
      'm4a',  'mp3',  'wav',  'html',
      'pdf',  'yaml', 'yml',  'otf',
      'ttf',  'zip'
    ],
    sourceExts: [ 'js', 'jsx', 'json', 'ts', 'tsx', 'svg' ]
  }
}

Broken config:

{
  resolver: {
    assetExts: [
      'bmp',  'gif',  'jpg',  'jpeg',
      'png',  'psd',  'webp', 'm4v',
      'mov',  'mp4',  'mpeg', 'mpg',
      'webm', 'aac',  'aiff', 'caf',
      'm4a',  'mp3',  'wav',  'html',
      'pdf',  'yaml', 'yml',  'otf',
      'ttf',  'zip'
    ],
    assetResolutions: [ '1', '1.5', '2', '3', '4' ],
    platforms: [ 'android', 'ios' ],
    sourceExts: [ 'js', 'jsx', 'json', 'ts', 'tsx', 'svg' ],
    blockList: /(\/__tests__\/.*)$/,
    dependencyExtractor: undefined,
    disableHierarchicalLookup: false,
    unstable_enableSymlinks: false,
    emptyModulePath: '/Users/benjamin/repos/nomad-react-native/node_modules/metro-runtime/src/modules/empty-module.js',
    extraNodeModules: {},
    hasteImplModulePath: undefined,
    nodeModulesPaths: [],
    resolveRequest: null,
    resolverMainFields: [ 'react-native', 'browser', 'main' ],
    unstable_conditionNames: [ 'require', 'import', 'react-native' ],
    unstable_conditionsByPlatform: { web: [Array] },
    unstable_enablePackageExports: false,
    useWatchman: true,
    requireCycleIgnorePatterns: [ /(^|\/|\\)node_modules($|\/|\\)/ ]
  },
  serializer: {
    polyfillModuleNames: [],
    getRunModuleStatement: [Function: getRunModuleStatement],
    getPolyfills: [Function: getPolyfills],
    getModulesRunBeforeMainModule: [Function: getModulesRunBeforeMainModule],
    processModuleFilter: [Function: processModuleFilter],
    createModuleIdFactory: [Function: createModuleIdFactory],
    experimentalSerializerHook: [Function: experimentalSerializerHook],
    customSerializer: null,
    isThirdPartyModule: [Function: isThirdPartyModule]
  },
  server: {
    enhanceMiddleware: [Function: enhanceMiddleware],
    port: 8081,
    rewriteRequestUrl: [Function: rewriteRequestUrl],
    runInspectorProxy: true,
    unstable_serverRoot: null,
    useGlobalHotkey: true,
    verifyConnections: false
  },
  symbolicator: {
    customizeFrame: [Function: customizeFrame],
    customizeStack: [AsyncFunction: customizeStack]
  },
  transformer: {
    assetPlugins: [],
    asyncRequireModulePath: '/Users/benjamin/repos/nomad-react-native/node_modules/metro-runtime/src/modules/asyncRequire.js',
    assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
    babelTransformerPath: '/Users/benjamin/repos/nomad-react-native/node_modules/react-native-svg-transformer/index.js',
    dynamicDepsInPackages: 'throwAtRuntime',
    enableBabelRCLookup: true,
    enableBabelRuntime: true,
    getTransformOptions: [AsyncFunction: getTransformOptions],
    globalPrefix: '',
    hermesParser: false,
    minifierConfig: { keep_classnames: true, keep_fnames: true, mangle: [Object] },
    minifierPath: 'metro-minify-terser',
    optimizationSizeLimit: 153600,
    transformVariants: { default: {} },
    workerPath: 'metro/src/DeltaBundler/Worker',
    publicPath: '/assets',
    allowOptionalDependencies: true,
    unstable_allowRequireContext: false,
    unstable_dependencyMapReservedName: null,
    unstable_disableModuleWrapping: false,
    unstable_disableNormalizePseudoGlobals: false,
    unstable_compactOutput: false
  },
  watcher: {
    additionalExts: [ 'cjs', 'mjs' ],
    healthCheck: {
      enabled: false,
      filePrefix: '.metro-health-check',
      interval: 30000,
      timeout: 5000
    },
    watchman: { deferStates: [Array] }
  },
  cacheStores: [
    FileStore {
      _root: '/var/folders/7l/9s2g11pn15j909ph6q5zgy080000gp/T/metro-cache'
    }
  ],
  cacheVersion: '1.0',
  projectRoot: '/Users/benjamin/repos/nomad-react-native',
  stickyWorkers: true,
  watchFolders: [],
  transformerPath: 'metro-transform-worker',
  maxWorkers: 2,
  resetCache: false,
  reporter: TerminalReporter {
    _activeBundles: Map(0) {},
    _scheduleUpdateBundleProgress: [Function: debounced] {
      cancel: [Function: cancel],
      flush: [Function: flush]
    },
    terminal: Terminal {
      _logLines: [],
      _nextStatusStr: '',
      _scheduleUpdate: [Function],
      _statusStr: '',
      _stream: [WriteStream]
    }
  },
  unstable_perfLoggerFactory: [Function (anonymous)]
}

I may need to individually remove these extra entries to find the one one that is causing my issue, but I was wondering if anyone has ideas as to which configuration option (or options) specifically could be causing my issue.

Reproducible demo

Don't have one yet

bhandanyan-nomad commented 1 month ago

metro.config.js file contents:

const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');

let defaultConfig = getDefaultConfig(__dirname);
const { assetExts, sourceExts } = defaultConfig.resolver;

/**
 * Metro configuration
 * https://reactnative.dev/docs/metro
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {
  transformer: {
    babelTransformerPath: require.resolve('react-native-svg-transformer'),
    minifierConfig: {
      keep_classnames: true, // Preserve class names
      keep_fnames: true, // Preserve function names
      mangle: {
        keep_classnames: true, // Preserve class names
        keep_fnames: true, // Preserve function names
      },
    },
  },
  maxWorkers: 2,
  resolver: {
    assetExts: assetExts.filter(ext => ext !== 'svg'),
    sourceExts: [...sourceExts, 'svg'],
  },
};

// If I use just the local config, my app works in an iOS simulator
// Produced the working config in issue description
// console.log(config);
// module.exports = config;

// If I use the merged config, my app breaks in the iOS simulator
const merged = mergeConfig(defaultConfig, config);
// Produced the broken config in issue description
// console.log(merged);
module.exports = merged;
bhandanyan-nomad commented 1 month ago

It seems the issue is specifically getTransformOptions

If I add delete merged.transformer.getTransformOptions; to my metro config my app works again