CONCEPT Cited by 1 source
React Native as a package¶
React Native as a package is an architectural pattern for integrating React Native into an existing large native iOS/Android codebase without requiring a full-app rewrite or git-submodule-style coupling. The pattern is named and canonicalised by Zalando's 2025-10 post and generalised by Callstack's open-source package.
The shape¶
Three parts:
- Entry Point — an npm package containing the React Root Component + RN initialisation logic. This is the single unit of truth for the RN side of the integration.
- Standalone Developer App — a greenfield RN app that consumes the Entry Point. Gives RN contributors a fast-iteration environment without needing to build the full legacy native app. See concepts/greenfield-developer-app-for-hybrid-engineers.
- Native Framework SDK — a native library (iOS + Android)
that also consumes the Entry Point, but exposes RN
functionality behind a simple native-framework-shaped
API (e.g.
ReactNativeViewFactory.loadView(...)). This is what the legacy native app links against.
Entry Point (npm)
│
├── Developer App (greenfield RN, fast iteration)
│
└── Framework SDK (native wrapper)
│
└── Legacy Native App (links SDK like any framework)
Why the pattern exists¶
Naïve RN brownfield integration fails on three axes — all three are why Zalando moved to this pattern (see concepts/brownfield-rn-integration):
- Native-dependency conflicts — RN's native modules or community packages disagree with the main app's versions of the same native deps.
- No clear separation — git submodules and similar integration approaches don't isolate RN from legacy code.
- Bad developer experience — building the full legacy app just to iterate on RN is slow and requires Xcode/Android Studio expertise, friction-loading web engineers who are expected to contribute.
Packaging RN into an npm module addresses all three:
- Dep resolution happens in one place (the Entry Point's
package.json). - Separation is enforced by the package boundary — the legacy app links only the SDK's native surface, not RN source.
- Developer experience is restored via the Developer App — contributors iterate without building the full native app.
What differs from "normal" RN¶
A standard RN app has one consumer: the platform launcher (Xcode / Android Studio). The "RN as a package" architecture has two consumers of the same Entry Point, which is the design constraint that shapes everything:
- The package API must be stable enough to be consumed by two independent codebases.
- Initialisation must be parameterised (deep-link props, launch options, screen parameters) so different hosts can route into the RN layer.
- Native interop — wishlist-badge, session state, navigation — must be abstracted behind Turbo Module + DI contracts because the Developer App can't call the legacy app's code and needs to mock those contracts.
Seen in¶
- sources/2025-10-02-zalando-accelerating-mobile-app-development-with-rendering-engine-and-react-native —
canonical wiki first instance. Zalando names the pattern
("React Native as a package") and documents the full
Entry Point + Developer App + Framework SDK triple.
Callstack is credited with generalising the pattern via
@callstack/react-native-brownfield.
Related¶
- concepts/brownfield-rn-integration — the problem space.
- concepts/greenfield-developer-app-for-hybrid-engineers — the Developer App concept.
- concepts/turbo-module-di-contract — how the package integrates with the legacy app at runtime.
- patterns/rn-as-consumable-npm-entry-point — the pattern.
- patterns/standalone-developer-app-for-rn — paired pattern.
- systems/callstack-react-native-brownfield
- systems/zalando-mobile-framework-sdk
- systems/zalando-mobile-developer-app