How to downgrade all NPM packages to compatible versions after upgrading all dependencies?

I’m looking for a way to upgrade all NPM packages in one command, incl. major versions and updating the package.json. This should also upgrade expo using the CLI, but it should make sure that my packages stay compatible.

Simply running expo-cli upgrade is not sufficient, because I might have other NPM packages that won’t be upgraded in this step.

I installed npm-check-updates to forcefully upgrade all packages (incl. expo-cli) and update the contents of the package.json simultaneously. Then I try to upgrade expo in the hope that it downgrades all packages that are too high, again, but it does not.


  "scripts": {
    "upgrade": "npm-check-updates -u && expo-cli upgrade && shx rm package-lock.json && expo install"

Running npm run upgrade causes:

npm ERR! While resolving: react-native@0.69.4
npm ERR! Found: react@18.2.0
npm ERR! node_modules/react
npm ERR!   react@"18.2.0" from the root project
npm ERR!   peer react@"^18.2.0" from react-dom@18.2.0

This is, because npm-check-updates -u will upgrade reactto 18.2.0, although the current expo SDK supports on 18.0.0.

According to @brentvatne and @bsgbryan expo-cli upgrade (formerly expo upgrade) should indeed downgrade my packages and it should update the contents of the package.json in that process, right?

I know, that my script will most likely cause issues in my code. The command is not designed to run any now and then, but only to port the app to the most recent dependencies possible.

Here is my full package.json:

  "name": "my-app",
  "version": "0.0.1",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "pre": "shx cp -n .env.example .env",
    "start": "npm run pre && expo start && npm run post",
    "android": "npm run pre && expo start --android && npm run post",
    "ios": "npm run pre && expo start --ios && npm run post",
    "web": "npm run pre && cross-env NODE_OPTIONS=--openssl-legacy-provider expo start --web && npm run post",
    "post": "",
    "upgrade": "npm-check-updates -u && expo-cli upgrade && shx rm package-lock.json && expo install"
  "dependencies": {
    "@expo/webpack-config": "^0.17.0",
    "expo": "~46.0.8",
    "expo-status-bar": "~1.4.0",
    "react": "18.0.0",
    "react-dom": "18.0.0",
    "react-native": "0.69.4",
    "react-native-dotenv": "^3.3.1",
    "react-native-web": "~0.18.7"
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "cross-env": "^7.0.3",
    "expo-cli": "^6.0.5",
    "npm-check-updates": "^16.0.5",
    "shx": "^0.3.4"
  "private": true

Upgrading everything to latest automatically sounds risky and I can’t guarantee you will not run into issues in the future, even if this suggestion works right now, but you may have luck with expo-cli doctor --fix-dependencies. I noticed that, if I downgrade my SDK to 45, run yarn, and then run expo-cli doctor --fix-dependencies, it will downgrade everything it tracks to the known compatible version.


@keith-kurak Thank you, this works.

A word of acknowledge: I am aware of the risks and I expect things to break. In the future, I just want a one liner to force upgrade all dependencies to be on the latest possible version. This will only be done on a special branch and causes a lot of testing to make sure things keep working.

By no means will I run this blindly, but I wish to have the possibility to jump into the cold water without wasting my time with installing every package manually using expo install.

For reference here is my full wild west command: npx npm-check-updates -u && npx expo-cli upgrade && npx expo-cli doctor --fix-dependencies && npx shx rm package-lock.json && npx expo install

1 Like

Glad it works- I hear where you’re coming from :slight_smile: , and I have to admit your approach has the distinct advantage of avoiding non-expo dependencies from falling behind on updates (something that’s been a struggle with my projects in the past), especially since you appreciate the trial-and-error and testing that goes into updating deps. Appreciate you sharing your script!

1 Like

You got it. :slight_smile: That’s the very reason why I wanted to have such one liner, to allow all my packages to catch up. It’s feels mandatory to me, because I maintain a rich Expo+Directus template that I plan to publish in the future.

Here is my opimized NPM script:

"upgrade:unmanaged": "npm-check-updates -u && npm i expo-cli eas-cli -g -D && expo-cli upgrade && expo-cli doctor --fix-dependencies"

The fix will actually clean the node_modules and package-lock.json, so no need to tamper with that. Works like charm, and ironically, today it helped me to fix my build instead of destroying it. Haha.

1 Like

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.