I built one React Native markets app with six data layers — Relay, TanStack Query, RTK Query, Zustand, Jotai, and hand-rolled vanilla — and measured the JS-thread CPU each one burns on a low-end Samsung. The full-fledged server-state libraries buy you real features, but on every cache write (including every live-price tick) you pay for them. Here's the bill.
I benchmarked Animated (native driver), Reanimated 4, and react-native-ease across four animation types on Android — measuring UI + JS frame drops, per-thread CPU, and memory. The winner depends on whether a gesture is involved — plus what Worklets Bundle Mode does to Reanimated's memory.
Verifying whether Expo Router's file-based routing actually solves the eager-aggregator problem — require.context getters, getComponent thunks, and a probe proving route discovery loads zero screens.
We turned on inlineRequires on a large production app and the startup profile barely moved. The reason: eager aggregators — modules that require dozens of others at init time, which the transform structurally cannot defer.
What inlineRequires actually does to your bundle — before/after Metro output, why Expo keeps it off by default, why default imports defeat it on stock RN, and what rnx-kit's tree shaking really changes.
A Hermes CPU profile showed our Android app spending 2.8 seconds on module resolution alone. That one finding kicked off a full investigation into inlined requires, eager aggregators, and how Expo Router handles this by default.