Moving a React Native (Expo) Project to a New Computer — Copying Without node_modules, Then Restoring the Environment
Why leave node_modules out when moving a project
I needed to move my dev environment to a new computer. My first instinct was to just copy the whole React Native (Expo) project folder as-is, but opening the folder reveals node_modules alone easily running past several hundred MB, even a full GB. Tens of thousands of files, too — the copy itself is slow and sometimes stalls mid-way.
So the usual move is to copy everything except node_modules. This folder is, after all, "a cache you can regenerate." What actually matters are two files that record exactly which packages at which versions you're using: package.json and package-lock.json. With just these two, you can regenerate an identical node_modules on the new computer.
This time, I copied my project over from the old computer with only node_modules left out. This post is a straightforward record of actually restoring that moved project to a working state. It's not just "run npm install and you're done" — it also covers an nvm trap I ran into along the way, and the steps to verify the restoration actually worked.
📌 This post is Part 1 — Restoration. The follow-up, covering reviving dependencies through Android native builds and installing on a real device, is in Part 2 — Building an RN Project on a New Laptop.
Pre-check: what's here, what's missing
Before starting the restoration, it's worth assessing the current state. A step to visually confirm what's missing from the folder you moved over.
ls -la
My project looked like this.
| Item | Status | Meaning |
|---|---|---|
package.json | Present | dependency list — the core of the restoration |
package-lock.json | Present | locked version info — lets you reproduce identically |
android/ | Present | native project folder, copied as-is |
src/, App.tsx | Present | source code, as-is |
node_modules/ | Missing | the target to restore |
The key detail is that package-lock.json came along too. With it, you can restore not just "similar versions" but versions exactly identical to the old computer. This is exactly why I use npm ci rather than npm install later.
Step 1. Confirm Node is actually recognized (the first trap)
Installing dependencies obviously needs Node.js. So I checked the version first:
node -v
# zsh: command not found: node
command not found. I assumed the new computer had no Node at all, but actually, nvm was installed — the shell just wasn't loading it.
nvm (Node Version Manager) is a tool that lets you install multiple Node.js versions and pick which one to use. But nvm needs to be "loaded" once from a shell config file like
~/.zshrcwhen a terminal opens, for thenodecommand to become active. Miss that load line, and even with Node installed via nvm,nodecan't be found.
I first checked which Node versions nvm actually had installed.
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # manually load nvm
nvm ls
v24.17.0 was right there, properly installed. So it wasn't that Node was missing — the shell just wasn't auto-loading nvm. This gets permanently fixed in Step 4. For now, loading it manually like above makes node, npm, and npx all work within that same terminal session.
Step 2. Restore dependencies with npm ci
Now the core part. Reviving node_modules.
npm ci
Why npm ci instead of npm install:
npm install | npm ci | |
|---|---|---|
| Reference file | package.json | package-lock.json |
| Versions | can update to the latest within range | stays exactly at the locked versions |
| Existing node_modules | partial update | wiped entirely and reinstalled fresh |
| Reproducibility | relatively lower | exactly identical reproduction |
When restoring a moved project, the goal is "an identical state to the old computer," so npm ci is the right call. Since it follows the lock file exactly, it prevents subtle bugs from unintended version bumps.
Here's the result.
added 634 packages, and audited 635 packages in 29s
634 packages restored in 30 seconds. You might see a pile of npm warn deprecated ... or N vulnerabilities warnings along the way — that's common noise in the library ecosystem. You can ignore these at the restoration stage. If the project ran fine before you moved it, these warnings aren't new problems — they were already there.
Step 3. Verify the restoration actually worked
npm ci finishing without an error isn't the end. Whether every package installed is a separate question from whether the code actually compiles. I checked two things.
3-1. TypeScript type check
npx tsc --noEmit
--noEmit means "just run the type check, don't actually emit any JS output." No output means no type errors. In my case, it passed cleanly. Passing this at least guarantees "the type-definition packages restored properly, and they line up with the source code's version."
3-2. Expo dependency compatibility check
For an Expo project, there's one more step. Expo has a recommended version per package for each SDK version — "this package needs to be this version to be compatible."
npx expo install --check
Result:
The following packages should be updated for best compatibility:
expo@54.0.34 - expected version: ~54.0.35
expo-localization@17.0.8 - expected version: ~17.0.9
It flags a slight patch-version mismatch. This kind of gap barely affects actual usage, but if you want it perfectly aligned, sync it to Expo's recommended versions like this.
npx expo install expo expo-localization
Tip: when adding packages to an Expo project, it's worth building the habit of using
npx expo installinstead ofnpm install. It automatically picks the version compatible with your current SDK.
Step 4. Permanently fixing nvm's auto-load
Back to the "can't find node" issue from Step 1. Manually loading nvm every single terminal session is tedious. Check whether these two lines exist in ~/.zshrc, and add them if not.
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
Once added, reload the config.
source ~/.zshrc
node -v # now v24.17.0 shows up right away
Do this, and node, npm, npx, npx expo start all work immediately even in a fresh terminal. This is a commonly missed step right after setting up a new computer, so it's worth flagging.
Frequently used restoration commands, summarized
# 0) (on a new computer) confirm nvm is loaded
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
node -v
# 1) restore all dependencies exactly, based on the lock file
npm ci
# 2) verify code consistency via type check
npx tsc --noEmit
# 3) (Expo) check / align SDK-compatible versions
npx expo install --check
npx expo install <package-name>
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
node: command not found | nvm not loaded into the shell | add the nvm load lines to ~/.zshrc, then source ~/.zshrc |
npm ci fails, says no lock file | package-lock.json is missing | fall back to npm install (versions may update, unfortunately) |
Version mismatch error during npm ci | package.json and the lock file are out of sync | reconcile them, or regenerate the lock file with npm install |
| deprecated / vulnerabilities warnings | ecosystem noise | ignore at the restoration stage — unrelated to functionality |
| Expo package version warning | slight mismatch from the SDK's recommended version | align it with npx expo install <package> |
Summary — the restoration flow at a glance
Here's the whole flow of reviving a React Native (Expo) project moved to a new computer without node_modules, summarized.
- Assess the current state — confirm
package.jsonandpackage-lock.jsonboth came along (these two are the prerequisite for restoration) - Check Node — if
node -vfails, suspect an nvm-loading issue first npm ci— restore dependencies exactly identical to the old environment, based on the lock file- Verify — check types with
npx tsc --noEmit, check SDK compatibility withnpx expo install --check - Wrap up — permanently fix the terminal environment by adding the nvm-loading lines to
~/.zshrc
The key mindset is that node_modules is a cache, not baggage. No need to lug it around heavily — as long as you keep the lock file safe, you can restore an identical environment on any computer in about 30 seconds. It's tempting to just install and call it done right after moving, but adding one type check and one compatibility check clears out the common trap of "I definitely installed it, but it won't run" ahead of time.
backtodev
A 40-something PM returns to code. Learning, failing, and growing.