Edit this page
Learn about Continuous Native Generation (CNG) and how it works.
A single native project on its own is complicated to maintain, scale, and update. In a cross-platform app, you have multiple native projects that you must maintain and keep up to date with the latest operating system releases to avoid falling too far behind in any third-party dependencies.
As your project grows, the complexity involved with each third-party dependency increases and makes the app nearly impossible to upgrade — this drastically slows down developer momentum, discourages adding complex native functionality, and leads to less powerful apps. To combat these issues, we formalized a process called Continuous Native Generation (CNG).
Continuous Native Generation is an abstract concept that describes the process of generating ephemeral native projects from a set of inputs. The inputs are typically a combination of configuration and code, and the output is a native project that can be compiled into a native app. We coined this term to describe the process used by Expo Prebuild to generate native projects for React Native apps, however, the concept is not limited to React Native or cross-platform apps.
Any React Native app can leverage Continuous Native Generation by using Expo Prebuild. This enables you to automate upgrading React Native, installing/uninstalling libraries, white-labeling at scale, sharing config across multiple apps, generating assets, reducing orphaned code, and more — generally, it allows you to build more powerful apps, at larger scales, without compromising on iteration speed.
Expo as a framework enables Continuous Native Generation by combining the following tools:
npx expo prebuild
command.expo
that's installed in the project and corresponding prebuild template.This boils down to a workflow where a user can express any native application with the app config and generate that project continuously — by running npx expo prebuild
.
Many complex libraries and services already support CNG via Expo Prebuild such as, MapBox, OneSignal, Stripe, and React Native Firebase.
Libraries that don't have first-party integration are also supported in the community Config Plugins repository.
Expo Config Plugins have first-class support for building locally and adding to your project without any third-party intervention or npm publishing. This enables you to move fast and patch things!
Note: npm downloads do not exactly reflect the number of users. However, it provides a rough estimate of adoption.
React Native libraries can adopt CNG in various ways depending on the complexity of their libraries. We've outlined different scenarios for library adoption:
No native code or configuration side-effects: Libraries without native code or configuration side-effects, such as react-native-blurhash
, can seamlessly integrate with npx expo prebuild
. They can rely on Node Module Resolution and Expo Autolinking to link into the native project without requiring any additional configuration.
Native code with no additional setup after install: Libraries with native code can often be installed and linked automatically with Expo Autolinking which runs before the native app is built.
Additional configuration side-effects and setup: Libraries that require additional configuration side-effects can adopt CNG by creating Expo Config Plugins for their libraries. This approach enables library authors to automate adding values such as permission messages to the Info.plist, or injecting targets in the Xcode project.
Libraries Dependent on Native Runtime Hooks: Libraries that depend on specific native runtime hooks, such as intercepting the initial launch URL via the AppDelegate
, MainActivity
, MainApplication
, and so on, can utilize Lifecycle listeners to minimize the side-effects of their library.
While library authors' adoption of CNG is not a prerequisite for using npx expo prebuild
, it significantly enhances the user experience. If a library author has not yet adopted CNG, users can still use npx expo prebuild
by creating local Config Plugins to modify the native generation pipeline. This flexibility ensures that the adoption of CNG is accessible and beneficial to all users within the React Native community.
CNG is designed to empower developers to build better apps than they normally could, by dividing configuration into testable and maintainable pieces. This allows developers to build more powerful apps without compromising on iteration speed.
This pattern has been proven to work in the React Native community in the following ways.
React Native developers who don't use Continuous Native Generation have reported that upgrading their apps to the latest version of React Native is the number one weakness of the library as per React Native Survey (2022).
When using CNG, the upgrade process simply involves upgrading the npm dependencies, app config, and re-running npx expo prebuild --clean
.
The community has been able to convert difficult native features into simple configuration files, which has allowed developers to build more powerful apps without compromising on iteration speed.
Here are a few impressive examples:
["react-native-app-clip", { "name": "My App Clip" }]
.At any point, these features can be easily added, and just as easily removed, without any side effects. CNG allows developers to experiment with complex features, and iterate on them quickly without worrying about the long-term maintenance costs or potential orphaned code in their project or uncommitted native caches.
This nets out to better apps, built faster.
No, CNG is a versatile pattern that can be applied to any native project. While Expo Prebuild is a tool that implements CNG specifically for React Native projects, the concept itself is not limited to this framework.
Absolutely! CNG is an abstract concept that can be applied to any operating system. Take Expo for example, although Expo Prebuild officially implements CNG for Android and iOS, it also provides abstract platform support for users to create implementations for additional platforms.
Not at all. CNG is an open pattern that can be adopted by any community. We've defined the pattern abstractly to help other communities understand how they can adopt CNG for their own projects.
CNG shares similarities with SSG in that it generates a project from a set of inputs. However, CNG differs from SSG in its output; it generates native runtime code instead of static website code. This means the native project is generated on-demand, and the generated source code and configuration are discarded once the native project is compiled into a native app.
CNG is designed to manage the entire state of a native project continuously. As a result, it's not intended for use with existing brownfield projects. However, you can use CNG to generate a new native project, which can then be integrated into an existing brownfield project.