Skip to content

Latest commit

 

History

History
94 lines (67 loc) · 4.95 KB

metro-config-out-tree-platforms.md

File metadata and controls

94 lines (67 loc) · 4.95 KB
id title
metro-config-out-tree-platforms
Metro config for out of tree platforms

How to setup and diagnose issues with metro config for react-native-macos and react-native-windows. Many of the instructions within this document may refer just to react-native-windows, but the steps apply to react-native-macos in the same way.

Version requirements

The information here only applies to versions of react-native-macos >=0.62.11 and react-native-windows >=0.62.0. It is also required that you have @react-native-community/cli >=4.9.0. Older versions require a much more complex configuration which is not covered by this document.

What does the metro config for macOS/Windows need to do

The way that react-native-macos and react-native-windows provide an implementation for react-native is by providing an additional copy of the react-native JavaScript files that implement their respective platforms. This JavaScript code is not included in the react-native package. When you do an import from 'react-native' normally metro will look for node_modules/react-native somewhere up the file path to file that module. Unfortunately when using react-native-macos or react-native-windows this will return the wrong JavaScript code. A simple solution might be to add a metro-config that includes

resolver {
    extraNodeModules: {
        'react-native': <path-to-react-native-windows>
    }
}

While that would enable metro to find the correct JavaScript files when building a windows bundle, that config would not work for macOS, or iOS and Android. Instead what we really need is for metro to resolve react-native differently depending on which platform is being bundled at the time.

The solution is to provide metro a custom resolver that accounts for the current platform being resolved. As of @react-native-community/cli@4.9.0 a change was added to the react-native CLI to configure metro with a custom resolver that does just that.

Diagnosing metro config issues

The usual way that these show up is a failure something like

Error: Unable to resolve module `./Libraries/Components/AccessibilityInfo/AccessibilityInfo` from <Some file path here>

Its usually an import to AccessibilityInfo that fails, this is because this is the first module that react-native itself tries to resolve, which only includes a .ios and .android version of the file within react-native.

Reset your metro cache

Sometimes after bumping package versions or modifying your metro config, the metro cache can get out of sync. A simple thing to try is resetting metro's file cache. This can be done by running yarn start --reset-cache.

Verify the platform is installed and hooked into the CLI

Run npx react-native config. Look at the output and verify that the JSON contains either the platforms.macos.npmPackageName property or the platforms.windows.npmPackageName property (or both) depending on which platform you are using:

{
    ...
    "platforms": {
      "ios": {},
      "android": {},
      "macos": {
        "npmPackageName": "react-native-macos"
      },
      "windows": {
        "npmPackageName": "react-native-windows"
      }
    },
    ...
}

If in a mono-repo, verify that react-native-macos/react-native-windows is not in your exclusionList

You can run node -p require.resolve('react-native-windows') if you are not sure where react-native-windows is installed. Ensure that the react-native-windows folder is not included within the exclusionList in your metro.config.js.

Verify that react-native-macos/react-native-windows is in your watchFolders

By default metro config will see all files within your package's folder. Many package managers, especially when running in monorepos (yarn workspaces etc) will hoist packages to a location outside of the package's local file structure. In this case you may need to add addition folders to metros watch list. This can be done adding to metro config:

  watchFolders: [
    // Include hoisted modules
    path.resolve(__dirname, '../..', 'node_modules'),
  ],

The file location above should include the path to react-native-windows that is returned by the node -p require.resolve('react-native-windows').

If your setup includes symlinks

Various package managers may create symlinks within node_modules. Metro does not support following symlinks, so if node_modules/react-native-windows is a symlink metro will not be able to find it. If that is the case, you can add

resolver {
    extraNodeModules: {
        'react-native-windows': <path-to-react-native-windows>
    }
}

to your metro config to notify metro of the real location of react-native-windows.

Reset your cache again

If you were following these steps in order, you probably made a bunch of changes to your metro config file. Have you tired resetting the metro cache again? yarn start --reset-cache