javascriptreact-nativeimportnode-modulesmetro-bundler

React Native Metro Unable to resolve module


In the process of updating React Native from 0.69.10 to 0.70.9, I've updated Metro to v0.72.3

When running the App, I'm getting the error

error: Error: Unable to resolve module react-native-gesture-handler from /path-to-project/index.js: react-native-gesture-handler could not be found within the project or in these directories:
  node_modules
  ../node_modules
  ../../../../node_modules

However, I've checked node_modules and found out that node_modules/react-native-gesture-handler exists

This problem does not only happen for react-native-gesture-handler. It also happens for react-native-screens, redux-form and so on, which leads me to think that it's a Metro resolution issue.

However, the path that Metro mentions that it tried to look at seems correct, so I'm not sure what could be the case here

Before the upgrade, everything was working as expected

What I've tried

I've tried resetting cache when running the start script react-native start --reset-cache but it doesn't work

I've also tried to disable Hermes. Doesn't seem to be the case either

I've also cleared iOS and Android cache, clearing node_modules and re-installing everything, to no avail

I've also ensured that all metro packages are in the correct version v0.72.3

I've tried to clear cache via rm -rf ${TMPDIR:-/tmp}/metro-*, and it doesn't work either

I've also tried updating metro to the latest version at v0.76.4 by adding

  "resolutions": {
    "metro": "^0.76.4"
  },

But the same error occurs


Solution

  • Managed to got it working

    // metro.config.js
    
    module.exports = {
      resolver: {
        sourceExts: [
          ... other stuff
          'json' // <=== add this
        ]
      },
    };
    

    Reason being that there is a breaking change in v0.72.0 release (here)

    [Breaking] .json files will no longer be implicitly resolved if removed from resolver.sourceExts (https://github.com/facebook/metro/commit/a3dc30aa0d54d65d6dbd426662f59b0ec398a612)
    

    The resolver algorithm checks for each package's package.json to resolve to the file being put in main. Under the hood, it uses this._hasteFS.exists(packageJsonPath)

    Full investigation here

    Since context.doesFileExist checks for package.json (which is a json file), we will need to explicitly add json to resolver.sourceExts