Skip to content

CONCEPT Cited by 1 source

Platform-specific import resolution

Platform-specific import resolution is the bundler-level mechanism of resolving a single import statement to different files per target platform based on file extension. In the React Native ecosystem, this is implemented by Metro.

The mechanism

When Metro sees import "./Foo" with target platform ios (or android, native, web), it looks for files in priority order:

  • Foo.ios.ts — iOS-specific.
  • Foo.android.ts — Android-specific.
  • Foo.native.ts — both iOS and Android (generic "native" target).
  • Foo.ts — fallback (used on web or when no platform-specific variant exists).

The consumer writes the same import; the bundler picks the file at build time, with no runtime dispatch overhead.

Why it matters for cross-platform UI

A cross-platform UI abstraction like react-strict-dom necessarily covers only the intersection of what all target platforms support (see concepts/cross-platform-ui-subset-tradeoff). For everything outside that intersection, the code has to diverge per platform. Metro's file-resolution gives that divergence a clean shape:

  • One import path, one consumer contract.
  • Per-platform implementations live in sibling files.
  • Types live in a shared file (e.g. Foo.types.ts), so TypeScript can verify every implementation against the same interface.

The discipline is captured by Zalando's post (sources/2025-10-02-zalando-accelerating-mobile-app-development-with-rendering-engine-and-react-native): "Especially in a component library, this is great because even if you have completely different implementations for different platforms, as long as the component's props are the same the consumer doesn't really care about the underlying implementation and is fully abstracted away from platform-specific code. We started using a simple pattern where types would live in a separate file so that we can have safe type checking between multiple implementations."

Alternatives and why this wins

  • Runtime Platform.OS branching. Works but ships all platform code to every platform, increasing bundle size and pulling in native deps that may not exist on web.
  • Conditional imports via build flags. Works but requires a custom bundler config per consumer.
  • Metro file resolution. Zero config at the consumer — the filename is the signal, and Metro handles everything. Dead-code elimination handled by the bundler's normal tree-shaking.

Seen in

Last updated · 507 distilled / 1,218 read