DEV Community

irinaivanovaalex
irinaivanovaalex

Posted on

How I upgraded project from NX to the latest version 0.72.3 of React Native

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",
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

Image description

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 within NX:
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

Enter fullscreen mode Exit fullscreen mode

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: [],
})
Enter fullscreen mode Exit fullscreen mode

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",
Enter fullscreen mode Exit fullscreen mode

To sum up:

  1. Follow the update guide at this link.
  2. Upgrade library versions with NX.
  3. 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.

Translation of this article into Russian

Top comments (0)