Dependency bloat in React Native: why AI tools can't solve your upgrade pain
AI tools make it trivial to scaffold a React Native app in minutes. But ask anyone who's tried to ship that code six months later: the real wall is dependency rot, not missing features. The latest push for "dependency intelligence" shines a light on a problem AI can't automate away. Package Intelligence for React Native & Expo Teams promises visibility, but the root issue goes much deeper.
Modern mobile apps ship with 50–200 dependencies. Every Expo or React Native project collects packages for navigation, state, UI, analytics, and every SaaS du jour. The churn is relentless.
The thesis: Your AI model can write code, but it can't own your upgrades, spot breaking changes, or guarantee your app survives the next Expo major. Dependency bloat is the scaling wall no vibe-coder sees coming.
Dependency intelligence is just a band-aid
Package dashboards, alerts, and health heuristics sound great—until you realize most AI-coded projects don't even pin versions or document why a package was chosen. "Dependency intelligence" assumes there's a strategy to monitor, but AI-generated code rarely has one.
Here's a real package.json from a recent AI-generated Expo app:
{
"dependencies": {
"@react-navigation/native": "^6.1.6",
"expo": "~50.0.0",
"react-native-reanimated": "^3.7.0",
"moment": "^2.29.4",
"random-uuid": "^1.0.0"
}
}No rationale, no lockfile, no audit. The AI did what it was told—scaffold a feature—but gave zero thought to the long-term cost of each line. The only thing tracked is "what works now," not "what breaks later." When that project hits the next major Expo upgrade, nobody remembers why moment was chosen, or if random-uuid is still maintained.
Takeaway: You can't dashboard your way out of poor dependency hygiene. AI can suggest, but it can't maintain.
Version drift breaks faster than code
Upgrading dependencies is the silent killer. Any builder who's had to upgrade from Expo SDK 48 to 49 knows the pain: breaking changes, peer dep mismatches, and random UI regressions. AI-generated code doesn't know which APIs are stable or which libraries are dead. The result: a pile of warnings and a weekend lost to Stack Overflow.
Here's a concrete example: upgrading react-native-reanimated in an AI-generated project often triggers this error:
ERROR: Invariant Violation: "main" has not been registered. This can happen if:
* Metro is running from the wrong folder
* react-native-reanimated needs to be rebuiltThere's no automated fix. The AI model that scaffolded the code isn't tracking which versions are compatible, or that Expo 50 expects a rebuilt native module. Instead, you get cryptic errors with zero context.
Another common case: peer dependency mismatches. Try bumping @react-navigation/native by one major version, and you might see:
npm ERR! Could not resolve dependency:
npm ERR! peer @react-navigation/native@"^5.0.0" from @react-navigation/stack@5.14.9The AI didn't pin compatible versions, so you're left with a dependency stalemate.
Takeaway: Dependency upgrades are a human problem. AI can't patch what it doesn't understand.
AI scaffolding hides the real risk
Prompt-based coding tools pitch "just ship and iterate," but the hidden backlog is real: unexplained packages, unreviewed transitive dependencies, and code you can't actually own. The moment you hit a security advisory or a deprecated API, the AI is silent. You're left with a brittle codebase and a pile of TODOs.
Try running npm audit on a fresh AI-generated app. The warnings aren't theoretical:
found 12 vulnerabilities (4 moderate, 8 high) in 1372 scanned packagesMost of these are from transitive dependencies—packages you never picked, but that your AI model pulled in to satisfy a vague prompt. You own the risk, but not the rationale.
Another example: a simple expo install after AI scaffolding often upgrades half your stack, sometimes breaking native modules or rendering some packages incompatible. The AI doesn't warn you about this, and the resulting error messages often reference packages you've never seen.
Takeaway: If you didn't pick your dependencies, you can't trust your stack.
Maintenance is the scaling wall, not the model
Every builder wants "production in a weekend." But six months later, maintenance is the real bill. AI tools optimize for first-ship, not year-two support. Dependency rot compounds: every unpinned version, every abandoned package, every workaround the AI scribbled in a comment.
A real-world case: a team shipped an Expo app using AI scaffolding, only to discover that react-navigation v5 was deprecated. Upgrading to v6 broke deep linking and required a rewrite of three screens. The AI couldn't help. The project stalled.
Another example: a package like moment—often included by default in AI code—has been in maintenance mode since 2020. If your app depends on it, you're stuck with either unpatched vulnerabilities or a painful migration to something like date-fns.
Here's what an unmaintained dependency looks like in your yarn.lock:
moment@^2.29.4:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#..."
integrity sha512-...
deprecated "Moment.js is a legacy project now. Please use date-fns or Luxon."The AI didn't flag the deprecation; you get to discover it when a CVE drops.
Takeaway: If you can't upgrade, you can't scale. The model isn't your bottleneck—your package.json is.
Try-before-buy can't fix code you don't own
Some platforms let you "export" your AI-generated app or try a paid toolkit. But if you don't understand your dependencies, you're just renting a problem you can't see. Honest tools—like OTF's kits, Expo's official templates, or react-native-builder-bob—at least surface the stack and versions up front. The difference is transparency, not model smarts.
Here's a side-by-side:
AI-generated package.json:
{
"dependencies": {
"expo": "~50.0.0",
"react-native-paper": "^5.10.0"
}
}Expo official template:
{
"dependencies": {
"expo": "~50.0.0",
"react-native": "0.73.4",
"react-native-gesture-handler": "~2.12.0",
"react-native-reanimated": "~3.7.0"
}
}The official template pins versions, includes peer dependencies, and matches Expo's release notes. The AI-generated version is a black box—you're left guessing which dependencies are truly required and which are vestigial.
Takeaway: Try-before-buy is only honest if you see the real maintenance cost.
Transitive dependencies are the silent risk
Most developers focus on their direct dependencies, but in React Native and Expo, transitive dependencies make up 80%+ of your installed packages. AI scaffolding tools rarely surface these, and most dashboards only show top-level packages.
Run npm ls --depth=2 on a fresh Expo project and you'll see a web of indirect dependencies:
├─┬ expo@50.0.0
│ ├─┬ @expo/config@8.2.2
│ │ └── ajv@8.12.0
│ ├── ...If a critical security flaw hits ajv@8.12.0, will you know? The AI won't. Neither will most "dependency intelligence" tools unless you dig deep.
This is how seemingly innocuous updates trigger production incidents: a minor bump in a transitive package can break your build or introduce a vulnerability. Humans catch this by auditing, pinning, and curating dependencies. AI tools just scaffold and forget.
Takeaway: Transitive dependencies are the real iceberg. If you don't audit, you don't own.
The context you own is your moat
The only way to survive dependency hell is to own your stack: pin versions, document why you chose each library, and keep your upgrades boring. AI can scaffold, but it can't guarantee what happens when Expo 51 drops or a maintainer nukes an NPM package. Your context—what you know about your code and why—matters more than any model upgrade.
Keep a DECISIONS.md or a comment in your package.json for each non-obvious dependency:
// "moment": "^2.29.4" // Used only for legacy date parsing in onboarding, to be replaced by date-fns Q3 2024Pin all versions in your lockfile. Audit with npm audit and npm outdated monthly. Track which dependencies are critical versus replaceable. When you upgrade Expo or React Native, read the release notes—don't trust the AI to do it for you.
Takeaway: The code you own is the only code you can maintain. Dependency intelligence starts with you.
AI tools are getting better at scaffolding, but they can't solve your dependency debt. If you want to build apps that last, treat your package.json like production infrastructure—not a throwaway script. Maintenance is the wall. Own your code, or you're just renting someone else's problem.