Why my development build needs my computer: what Metro actually does
Cover: Stacks shipping containers Port Barcelona by Unknown, CC0 1.0.
Background
My app needed to test push notifications, which Expo Go can't do, so I made my first development build and installed it on my iPhone. I assumed I could take the phone out and test at my own pace.
As soon as I left my home Wi-Fi the app couldn't connect. The start command had always included a local port, and I had never thought about what it was for.
What I tried
- Treating the development build as a finished app: I only learned it needed my computer once I was out.
- Thinking Metro and Babel were the same thing: both "transform code", so I kept mixing them up.
- Planning a new build for every small change: most changes don't need a build at all.
How I did it
1. Understand what Metro is
Metro is the bundler built into React Native and Expo. When you run npx expo start, Metro is what starts. It does four things:
- Transform: turn TypeScript and JSX into plain JavaScript. It hands this step to Babel.
- Bundle: merge hundreds of files and packages into one bundle.
- Serve: run a small server on your computer that the phone downloads the bundle from.
- Watch: when you save, rebuild only what changed so the phone updates in seconds.
2. Tell Babel and a bundler apart
Babel is a transpiler. It turns newer syntax into older syntax one file at a time and doesn't merge anything. Metro is the bundler, the React Native version of webpack or Vite, and it calls Babel for the transform step.
3. See where the JavaScript lives
| Development build | Preview / production build | |
|---|---|---|
| Where the JavaScript is | Metro on your computer | Bundled inside the app |
| Computer must be on | Yes | No |
| After a code change | Visible in seconds | New build or an over-the-air update |
| Speed | Slower, debug mode | Release speed |
For a release build, Metro bundles the code once in the cloud and Hermes compiles it ahead of time into bytecode. The app starts faster and never needs Metro again.
4. Remember data still goes over the network
Whatever the build, only the screens and logic go inside the app. Signing in, loading data, placing orders and push notifications all go over the internet to the cloud. Metro is a development tool and has nothing to do with your users.
5. Testing away from home has two routes
- Keep the development build: expose Metro through a temporary tunnel and type its address into the app. The computer has to stay on.
- Make a preview build instead: the code is inside the app and needs no computer, but every change needs a new build.
Pitfalls
- The computer went to sleep: Metro stopped and the development build couldn't connect.
- Added a native package without rebuilding: the JavaScript updated but the new native feature never appeared until I built again.
- Thinking only a preview build could test push: a development build can too; the only difference is where the code comes from.
What improved
- Understanding: I now know the local port is Metro sending the code to the phone.
- Changing the UI: I save and see it in seconds, without using a build.
- Native changes: I batch them into one build instead of building whenever I think of one.
- Testing outside: I'm no longer stuck once I leave home; I pick a tunnel or a preview build.