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.
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.
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.
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
.
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
.
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"
}
},
...
}
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
.
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')
.
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
.
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