Updating react-native
is often associated with significant challenges for developers, often consuming a considerable amount of working time and effort, especially when a project utilizes numerous libraries or possesses a non-standard structure.
In this article, I will share the experiences I encountered in a project using the NX
monorepository and discuss what helped me overcome this issue.
Upgrading to the new version of React Native following the guide
Initial dependency versions:
"nx": "16.4.0",
"react-native": "0.71.10",
Having a monorepository, it was necessary to upgrade to the latest version of React Native
. Upon upgrading to version 0.72.3 using the React Native Helper, the projects build successfully, but we encounter an error:
react-native could not be found within the project or in these directories:
../../node_modules
> 1 | import { AppRegistry } from 'react-native'
The issue is that Metro
built the project somewhat incorrectly. The build process through Metro
involves several stages:
-
Metro
constructs a graph of all modules. - It transpiles modules into a format understandable by
React Native
. - Then, it serializes them, bundling the modules into one or more bundles.
However, since the project uses
NX
, its structure differs from the basic one, resulting in distinct configuration files at various project levels. Let's take a look at the repository structure withinNX
:
monorepo-name/
├── apps/
│ └── mobile/
│ ├── app.json
│ ├── metro.config.js
│ ├── package.json
│ ├── project.json
│ └── mobile-e2e/
├── libs/
│ └── shared-ui-layout/
│ ├── src/
│ │ └── index.ts
│ ├── .babelrc
│ ├── jest.config.js
│ ├── project.json
│ ├── README.md
│ ├── test-setup.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
├── tools/
├── babel.config.json
├── jest.config.js
├── jest.preset.js
├── nx.json
├── package-lock.json
├── package.json
└── tsconfig.base.json
Configurations Adjustment
In this project structure, each application has its set of configuration files, such as metro.config.js
, package.json
, and others. However, besides these configurations, there are also files in the repository's root directory that need to be taken into account during the build process. NX
itself provides the withNxMetro function, which allows merging NX
configurations and user-defined ones into a single configuration. As a result, to achieve the necessary configuration in the metro.config.js
file, we will make the following changes:
- We will begin by merging the default and user-defined configurations using the mergeConfig function, following the guidelines of the
React Native
guide. - Then, we will pass the result of this merge to the withNxMetro function to combine it with the
NX
configuration.
const { withNxMetro } = require('@nx/react-native')
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config')
const exclusionList = require('metro-config/src/defaults/exclusionList')
const defaultConfig = getDefaultConfig(__dirname)
const { assetExts, sourceExts } = defaultConfig.resolver
/**
* Metro configuration
* https://facebook.github.io/metro/docs/configuration
*
* @type {import('metro-config').MetroConfig}
*/
const customConfig = {
transformer: {
babelTransformerPath: require.resolve('react-native-svg-transformer'),
},
resolver: {
assetExts: assetExts.filter(ext => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg'],
blockList: exclusionList([/^(?!.*node_modules).*\/dist\/.*/]),
unstable_enableSymlinks: true,
unstable_enablePackageExports: true,
},
}
module.exports = withNxMetro(mergeConfig(defaultConfig, customConfig), {
// Change this to true to see debugging info.
// Useful if you have issues resolving modules
debug: false,
// all the file extensions used for imports other than 'ts', 'tsx', 'js', 'jsx', 'json'
extensions: [],
// Specify folders to watch, in addition to Nx defaults (workspace libraries and node_modules)
watchFolders: [],
})
After such an upgrade, the project's metro.config.js
will launch, and we'll see the initial app screen that we've been longing to see again. 🎉
Final library versions:
"nx": "16.6.0",
"react-native": "0.72.3",
To sum up:
- Follow the update guide at this link.
- Upgrade library versions with
NX
. - Modify the
metro.config.js
file.
Conclusion
I trust that this article provided a solution for individuals who faced this issue or are still utilizing outdated versions of NX
and React Native
.
Top comments (0)