Dependency Management
Ready for some magic? This guide will fundamentally change the way you maintain your React Native applications and libraries. It all centers on one tool -- the dependency manager.
Not quite ready to make the leap? Learn more about dependencies first.
Onboarding
The first order of business is onboarding your React Native packages to the dependency manager. Do this for every React Native package you have. It can be done all at once, or gradually over multiple PRs.
First, add the dependency manager to your package.
- Yarn
- pnpm
- npm
yarn add @rnx-kit/align-deps --dev
pnpm add -D @rnx-kit/align-deps
npm add --save-dev @rnx-kit/align-deps
Add new script commands for convenience. We'll use these later.
{
"scripts": {
"check-dependencies": "rnx-align-deps",
"fix-dependencies": "rnx-align-deps --write"
}
}
Next, generate the dependency manager configuration for your package. If your
package produces a bundle, it's an app
. Otherwise, it's a library
.
- Yarn
- pnpm
- npm
yarn rnx-align-deps --init app
yarn rnx-align-deps --init library
pnpm rnx-align-deps --init app
pnpm rnx-align-deps --init library
npx rnx-align-deps --init app
npx rnx-align-deps --init library
Fix any React Native package versions that might have compatibility issues.
- Yarn
- pnpm
- npm
yarn fix-dependencies
pnpm fix-dependencies
npx fix-dependencies
Review and test your changes before committing. This is important, even for seemingly harmless updates.
Automating Everything
Once onboarding is done, you're ready to set up automation.
Automation validates your React Native dependencies during builds and PRs. It also keeps the dependency manager up-to-date, including the built-in list of known/good React Native package versions and releases. This list can change frequently, based on the volatility of the React Native ecosystem.
Builds
To validate dependencies during a build, you'll integrate the
check-dependencies
command into your build workflow.
In each of your React Native packages, add it to the build
command:
{
"scripts": {
"build": "... existing-stuff ... && yarn fix-dependencies"
}
}
Replace yarn
with npm run
or pnpm
, depending on your package manager.
When the validation process finds a compatibility problem, it fails with a detailed message, showing you what went wrong before you commit to the repo.
If you're using a task runner like Lage or Gulp, you can go for a more
sophisticated integration. The advantage being that fix-dependencies
could run
as its own task with isolated logging and error handling. And, you can run it in
parallel with other tasks.
Pull Requests
To validate dependencies during PRs, you'll use the dependency manager to check every package in your repo.
Add the dependency manager to your repo's root package.json.
- Yarn
- pnpm
- npm
yarn add @rnx-kit/align-deps --dev -W
pnpm add -D @rnx-kit/align-deps
npm add --save-dev @rnx-kit/align-deps
Next, add this command to your PR loop. It runs the dependency manager from the
root of the repo, scanning all packages. This include packages which haven't
onboarded yet. For those, --requirements react-native@[version]
controls the
target React Native release to use when checking compatibility.
- Yarn
- pnpm
- npm
yarn rnx-align-deps --requirements react-native@0.66
pnpm rnx-align-deps --requirements react-native@0.66
npx rnx-align-deps --requirements react-native@0.66
When a compatibility problem is found, the command fails with a non-zero exit code, which causes the PR loop to fail. This protects the repo from risky changes.
In the PR logs, you'll see a detailed report, in diff
format, explaining what
went wrong.
error Found 3 violation(s) in 'packages/app/package.json':
react-native "^0.66.0" -> "^0.66.0-0" (dependencies)
react-native-macos "^0.66.0" -> "^0.66.0-0" (dependencies)
react-native-windows "^0.66.0" -> "^0.66.0-0" (dependencies)
- Current
+ Expected
{
"name": "@rnts/button",
"version": "0.0.1",
"private": true,
"license": "MIT",
"main": "src/index.ts",
"typings": "lib/index.d.ts",
"scripts": {
"clean": "rimraf ./lib",
"build": "yarn run clean && yarn run tsc && yarn run api-extract",
"api-extract": "api-extractor run --local --verbose"
},
"devDependencies": {
"@microsoft/api-extractor": "^7.19.4",
"@office-iss/react-native-win32": "^0.66.0",
"@rnx-kit/align-deps": "^2.0.0",
"@types/react-native": "^0.66.0",
- "rimraf": "^3.0.2",
"react": "17.0.2",
- "react-native": "^0.66.0",
- "react-native-macos": "^0.66.0",
- "react-native-windows": "^0.66.0",
+ "react-native": "^0.66.0-0",
+ "react-native-macos": "^0.66.0-0",
+ "react-native-windows": "^0.66.0-0",
+ "rimraf": "^3.0.2",
"typescript": "^4.5.5"
},
"rnx-kit": {
"kitType": "library",
"alignDeps": {
"requirements": {
"development": ["react-native@0.66"],
"production": ["react-native@0.66"]
},
"capabilities": [
"core-android",
"core-ios",
"core-macos",
"core-windows",
"react"
]
}
+ },
+ "peerDependencies": {
+ "react": "17.0.2",
+ "react-native": "^0.66.0-0",
+ "react-native-macos": "^0.66.0-0",
+ "react-native-windows": "^0.66.0-0"
}
}
error 'packages/button/package.json': Changes are needed to satisfy all requirements. Re-run with `--write` to apply them.
info Visit https://aka.ms/align-deps information about align-deps.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Fixing problems is automated, too! From your development terminal, run the same
command with a --write
parameter.
- Yarn
- pnpm
- npm
yarn rnx-align-deps --requirements react-native@0.66 --write
pnpm rnx-align-deps --requirements react-native@0.66 --write
npx rnx-align-deps --requirements react-native@0.66 --write
Review and test the fixes before pushing them to your PR.
Dependency Manager Updates
The dependency manager comes with a built-in list of known/good React Native package versions and releases. Keeping the dependency manager up-to-date gives you the latest compatibility data.
If you are in GitHub, use Dependabot to keep your packages up-to-date, including the dependency manager. If you host your repo elsewhere, you can use tools like Snyk instead.
When a dependency manager update happens, the associated PR loop may fail with incompatible package errors. This is OK. It means the built-in list of React Native package versions has changed, and you need to update your packages in response.
Run this command from the root of your repo. It uses the dependency manager to make the fixes automatically.
- Yarn
- pnpm
- npm
yarn rnx-align-deps --write
pnpm rnx-align-deps --write
npx rnx-align-deps --write
Review and test the fixes before pushing them to the PR with the dependency manager update.
Upgrading React Native
When you're ready to upgrade to a new release of React Native (or downgrade to an old release), you can use the dependency manager to help you out.
First, update your PR loop definition. Find the
rnx-align-deps --requirements react-native@[version]
command and change the
target React Native version.
Then, run these commands from the root of your repo to change your React Native
version and adjust all React Native dependencies to be compatible. Replace
[version]
with your target React Native version in major.minor
format, such
as "0.66" or "0.68".
- Yarn
- pnpm
- npm
yarn rnx-align-deps --set-version [version]
pnpm rnx-align-deps --set-version [version]
npx rnx-align-deps --set-version [version]
- Yarn
- pnpm
- npm
yarn rnx-align-deps --requirements react-native@[version] --write
pnpm rnx-align-deps --requirements react-native@[version] --write
npx rnx-align-deps --requirements react-native@[version] --write
Review and test your packages thoroughly before merging these changes.
Customization
Did you know that you can add your own packages to the dependency manager's built-in list?
If your repo uses React Native packages that aren't known to the dependency manager, add them to the list! Or if you want to align other dependencies automatically, add them to the list too!
First, write the list of packages you want to manage. Each one is expressed as a
capability. You can use a .js
module, a .json
file, or a module name.
{
"0.66": {
"@types/node": {
"name": "@types/node",
"version": "^16.0.0",
"devOnly": true
},
"chalk": {
"name": "chalk",
"version": "^4.1.0"
},
"native-base": {
"name": "native-base",
"version": "^3.3.11",
"capabilities": ["react"]
}
}
}
Look at native-base
in the example above. It's wrapped in a 0.66
version
tag. That means it only applies to React Native 0.66.
Next, configure each of your onboarded React Native packages to use the list.
{
"rnx-kit": {
"alignDeps": {
+ "presets": [
+ "microsoft/react-native",
+ "path/to/dependency-profile.json"
+ ],
"requirements": {
"development": ["react-native@0.66"],
"production": ["react-native@0.66"]
},
"capabilities": [
"core-android",
"core-ios",
"core-macos",
"core-windows",
"react"
]
}
}
}
Now it's time to use the list. Run the dependency manager to update all of your packages.
- Yarn
- pnpm
- npm
yarn rnx-align-deps --requirements react-native@0.66 --presets microsoft/react-native,path/to/dependency-profile.json --write
pnpm rnx-align-deps --requirements react-native@0.66 --presets microsoft/react-native,path/to/dependency-profile.json --write
npx rnx-align-deps --requirements react-native@0.66 --presets microsoft/react-native,path/to/dependency-profile.json --write
Review and test the changes before continuing.
The last step is updating the automation. Each command needs an extra
--presets [paths]
parameter.
- Pull Requests: Change the
rnx-align-deps --requirements react-native@[version]
command - Dependency Manager Updates: Change the
rnx-align-deps --write
command - Upgrading React Native: Change the
rnx-align-deps --requirements react-native@[version] --write
command
Finish Line
Congratulations! Your React Native apps and libraries are now up-to-date and compatible with each other! And they should stay that way thanks to the automation you've put in place!
Was this helpful? Help spread the word on Twitter.
And, if you customized your list of dependencies, please consider contributing your work so that everyone can use it (including you). You can create an issue with your customizations or even submit a pull request.