new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Expo · EAS · all subjects

app-extensions/cng

46 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

App extension config plugin purpose

Config plugins let you add targets to the Xcode project that is generated during the Prebuild phase of a build job. They are able to modify the app config, and in most cases, if you are using a library that adds an extension then the config plugin will also add the required configuration to declare the extension in your app config.

CNG projects app extensions configuration

In Continuous Native Generation (CNG) projects, you can add app extensions by writing a config plugin or using a library that creates an extension with its own config plugin. App extensions are declared using extra.eas.build.experimental.ios.appExtensions in the app config, allowing EAS CLI to know what app extensions exist before the build starts and before the Xcode project has been generated.

App extension app.json example

{ "expo": { "extra": { "eas": { "build": { "experimental": { "ios": { "appExtensions": [ { "targetName": "myappextension", "bundleIdentifier": "com.myapp.extension", "entitlements": { "com.apple.example": "entitlement value" } } ] } } } } } } }

App extension configuration in app.json

App extensions are configured in app.json under the path extra.eas.build.experimental.ios.appExtensions. Each extension object requires a targetName string and bundleIdentifier string. The entitlements property is an object containing entitlements as key-value pairs.

Monorepo with Continuous Native Generation (CNG)

If you are building a project that uses Continuous Native Generation in a monorepo, consult the Working with Monorepos guide.

Prebuild template customization

Prebuild starts from template files that are then modified with config plugins. The template files are based on the Expo SDK version and come from the npm package expo-template-bare-minimum. You can change the template used by passing --template /path/to/template.tgz to the npx expo prebuild command. This is not generally recommended because the base modifiers in @expo/prebuild-config make undocumented assumptions about the template files. In network environments where packages are downloaded from a private registry and npm public registry access is blocked, a locally-available template must be passed to the prebuild command.

Config plugins role in CNG

Config plugins are functions that perform modifications on native projects during prebuild. If you modify the generated android and ios directories manually, you risk losing your changes the next time you run npx expo prebuild --clean. Instead, use config plugins to express customizations.

CNG dependency warning behavior

Prebuild begins by initializing new native projects from a template corresponding to each Expo SDK version, which also aligns with specific React and React Native versions. You will see a warning when running npx expo prebuild if your project's React and React Native versions differ from the expected versions specified in the dependencies field of the template's package.json.

Prebuild --clean option behavior

The --clean option deletes any existing native directories before generating. Re-running npx expo prebuild without --clean will layer changes on top of existing files, which is faster but may not produce the same results in some cases. Using --clean is the safest way and generally recommended because some config plugins are not idempotent. When using --clean, you will be warned if you have uncommitted changes to your git repository, and this prompt is skipped in CI. This check can be disabled with the EXPO_NO_GIT_STATUS=1 environment variable.

App extension app.json configuration example

App extensions in CNG projects are configured in app.json under extra.eas.build.experimental.ios.appExtensions as an array. Each extension object contains: targetName (string, the extension target name), bundleIdentifier (string, the extension bundle ID), and entitlements (object, containing entitlement keys and values). Example: ```json { "expo": { "extra": { "eas": { "build": { "experimental": { "ios": { "appExtensions": [ { "targetName": "myappextension", "bundleIdentifier": "com.myapp.extension", "entitlements": { "com.apple.example": "entitlement value" } } ] } } } } } } } ```

extra.eas.build.experimental.ios.appExtensions configuration

Declaring app extensions with extra.eas.build.experimental.ios.appExtensions in your app config allows EAS CLI to know what app extensions exist before the build starts (before the Xcode project has been generated) to ensure that required credentials are generated and validated.

CNG projects app extensions configuration

In CNG projects, app extensions are declared using config plugins. You can add an app extension to your project by writing a config plugin or using a library that creates an extension with its own config plugin. Config plugins add targets to the Xcode project during the Prebuild phase of a build job.

Config plugins can modify app config for extensions

Config plugins are able to modify the app config. In most cases, if you are using a library that adds an extension, the config plugin will also add the required configuration to declare the extension in your app config. If writing a library, it is recommended to consider adding this functionality.

Git status warning with --clean option

When using the --clean option, a warning is displayed if there are uncommitted changes to the git repository, since this option will delete and recreate all native project files. This prompt is optional and is skipped in CI environments. The check can be disabled by setting the environment variable EXPO_NO_GIT_STATUS=1.

Custom prebuild templates with --template option

Native directory generation can be customized by passing --template /path/to/template.tgz to the npx expo prebuild command. This approach is not generally recommended because the base modifiers in @expo/prebuild-config make undocumented assumptions about template files, making custom templates tricky to maintain.

Default prebuild template source

Prebuild templates are based on the Expo SDK version and come from the npm package expo-template-bare-minimum. This is the default template source used when no custom template is specified.

Prebuild side effects on package.json

In addition to generating android and ios directories, npx expo prebuild performs side effects on the project: it modifies the scripts field in package.json to replace 'expo start --android' and 'expo start --ios' with 'expo run:android' and 'expo run:ios', and modifies the dependencies field in package.json. The convenience change to scripts is the only side effect that alters how developers work before/after prebuild.

Prebuild is optional and fully compatible with Expo tools

Prebuild is optional and works seamlessly with all Expo tools and services. For existing React Native projects where native projects are managed manually, npx expo prebuild should not be used as it may overwrite manual customizations. Developers can continue making direct changes to native projects while adopting other Expo tools. Later, manual customizations can be moved to app config and/or config plugins, then CNG can be adopted.

Expo tools support for non-Prebuild projects

All Expo offerings including EAS, Expo CLI, and Expo SDK libraries are built to fully support existing React Native projects that do not use npx expo prebuild. The only exception is Expo Go, which can load arbitrary React Native projects only if they include JavaScript fallbacks for native code absent in the Expo Go runtime.

CNG helps with React Native project upgrades

CNG simplifies the upgrade process to newer React Native versions. Instead of complex upgrades, developers using CNG simply bump versions in package.json, update the app config, and re-run npx expo prebuild --clean. This contrasts with the React Native Survey (2022) finding that upgrading was the top weakness for developers not using CNG.

CNG implementation in Expo framework

Expo as a framework enables CNG by combining: the app config file, arguments passed to npx expo prebuild, the installed expo version and corresponding prebuild template, autolinking for native modules in package.json, native subscribers for reducing side-effects in entry point files like MainApplication or AppDelegate, and EAS Credentials for code signing additional targets and entitlements.

Config plugins for native project customization

Config plugins are functions that perform modifications on native projects during prebuild. Many config plugins already exist for lots of modifications, and community libraries often ship their own. Developers can use existing plugins or create local config plugins if library authors have not yet adopted CNG.

Autolinking for native module linking

Autolinking automatically links native modules found in package.json before the native app is built. This runs as part of the Expo Prebuild process and enables seamless integration of native modules without manual configuration.

Prebuild addressing dependency side-effects

Many native packages require additional setup beyond installation and autolinking, such as adding permissions to AndroidManifest.xml or Info.plist. With Prebuild, library authors can create testable and versioned config plugins to automate adding required configuration side effects. For native code side effects, Android Lifecycle Listeners and AppDelegate Subscribers are available in the default prebuild template.

Prebuild reducing orphaned code

When a package is uninstalled without using Prebuild, all related side effects must be manually removed or they become orphaned code that builds up and makes the project harder to understand and maintain. With Prebuild, the only side effect is the config plugin in the project's Expo config (app.json), which will throw an error when the corresponding node module is uninstalled, preventing orphaned code.

Prebuild limitations: platform compatibility

Prebuild can only be used for native platforms supported by the Expo SDK, which are currently Android and iOS. Web does not require npx expo prebuild since it uses the browser instead of a custom native runtime.

Prebuild not ideal for rapid native experimentation

All native changes must be added with native modules or config plugins. If you want to quickly add a native file to experiment, you may be better off running prebuild, adding the file manually, then working your way back into the system. Config modifications require writing plugins, which can be slower if done often.

React Native library adoption patterns for CNG

Library authors can adopt CNG in multiple ways: libraries without native code or configuration side-effects can seamlessly integrate with prebuild via Node Module Resolution; libraries with native code can use Expo Autolinking; libraries with additional configuration side-effects can create Expo config plugins; libraries dependent on native runtime hooks can use Lifecycle Listeners or AppDelegate Subscribers from the Expo Modules API. Many complex libraries like MapBox, Sentry, Stripe, and React Native Firebase already support CNG.

CNG is not limited to React Native

CNG is a versatile pattern that can be applied to any native project, not just React Native. While Expo Prebuild implements CNG specifically for React Native projects, the concept itself is not framework-limited.

CNG does not require using Expo

CNG is an open pattern that can be adopted by any community. It is not limited to Expo; the pattern has been defined abstractly to help other communities understand how they can adopt CNG for their own projects.

CNG and Static Site Generation (SSG) comparison

CNG shares similarities with SSG in that both generate a project from a set of inputs. However, CNG differs in its output: it generates native runtime code instead of static website code. The native project is generated on-demand, and the generated source code and configuration are discarded once compiled into a native app.

Prebuild simplifying cross-platform configuration

Cross-platform configurations such as app icon, name, splash screen, and similar settings must be implemented manually in native code with different approaches per platform. With Prebuild, these configurations are handled at the config plugin level, requiring only a single value like 'icon': './icon.png' to handle all icon generation across platforms.

Incomplete community config plugin support

Not all packages support Expo Prebuild yet. If a library requires extra setup after installation and lacks a config plugin, a pull request or issue should be opened with the maintainer. External plugins exist in the out-of-tree config plugins repo for popular packages that haven't adopted the system yet, similar to DefinitelyTyped for TypeScript.

Community examples of CNG reducing complexity

CNG has enabled developers to convert difficult native features into simple configuration files: iOS Safari Extensions reduce to a few lines of JSON, iMessage Sticker Apps are generated from JSON, the entire Firebase suite reduces from multi-step native configuration to basic JSON, cross-platform home screen widgets are generated with a config plugin, and Apple App Clips reduce from multi-step target processes to a single line of configuration. These features can be easily added and removed without side effects.

Continuous Native Generation (CNG) definition

Continuous Native Generation is a concept where short-lived native projects are generated only when needed, such as when debugging or building. Instead of maintaining native projects for the lifetime of the codebase, projects are generated from a standard template plus configuration or custom code that defines how the template should be customized. The developer maintains only the definition of customizations rather than all native project code.

Prebuild command basic usage

Prebuild can be invoked using: npx expo prebuild (npm), yarn expo prebuild (yarn), pnpm expo prebuild (pnpm), or bun expo prebuild (bun). This command creates the android and ios directories for running React code.

Prebuild generates android and ios directories

Running npx expo prebuild creates the android and ios directories. If these directories are modified manually, changes will be lost on the next run of npx expo prebuild --clean. To make persistent modifications, use config plugins instead.

EAS Build automatic prebuild behavior

If a project does not contain android and ios directories, EAS Build will automatically run Prebuild to generate these native directories before compilation. This is the default behavior for projects created using npx create-expo-app. For projects that already have android and ios directories, EAS Build will not run Prebuild to avoid overwriting manual changes.

CNG not intended for existing brownfield projects

CNG is designed to manage the entire state of a native project continuously and is not intended for use with existing brownfield projects. However, CNG can generate a new native project which can then be integrated into an existing brownfield project.

Adding android and ios to .gitignore for Prebuild workflow

The android and ios directories are automatically added to .gitignore when creating a new project. If needed to add manually, these directories can be added to .gitignore or .easignore files to ensure Prebuild generates fresh native directories during the EAS Build process.

Local native builds with Expo CLI run commands

Local native builds can be performed using: npx expo run:android (or yarn/pnpm/bun equivalents) to build the native Android project, or npx expo run:ios (or yarn/pnpm/bun equivalents) to build the native iOS project. If native directories are absent, npx expo prebuild will run once for the specific platform. On subsequent uses, manually run npx expo prebuild --clean to ensure native code is freshly synchronized with local configuration.

Prebuild platform support and --platform option

Prebuild currently supports Android and iOS. Web support is not required because there is no native project to generate for web. Use the --platform option to run prebuild for individual platforms: npx expo prebuild --platform ios (or equivalents with yarn/pnpm/bun).

Prebuild template initialization from Expo SDK version

Prebuild begins by initializing new native projects from a template corresponding to each Expo SDK version. This template alignment includes specific React and React Native versions. A warning will display when running npx expo prebuild if the project's React and React Native versions differ from the expected versions specified in the template's package.json.

Skip dependency updates with --skip-dependency-update

The --skip-dependency-update option allows skipping changes to npm package versions during prebuild: npx expo prebuild --skip-dependency-update react-native,react (or equivalents with yarn/pnpm/bun). Package names should be comma-separated.

Package manager inference and forcing during Prebuild

When dependencies are changed, Prebuild will reinstall libraries using the package manager inferred from the project's lockfile. A specific package manager can be forced by providing: --npm, --yarn, or --pnpm flags. All installations can be skipped with --no-install, which is useful for testing generation quickly.

Prebuild --clean option behavior and non-idempotent plugins

The --clean option deletes existing native directories before generating. Running npx expo prebuild without --clean will layer changes on top of existing files, which is faster but may not produce the same results. Some config plugins are not idempotent; when multiple plugins use regex changes to modify code, unexpected behavior can occur. Using --clean is the safest approach and is generally recommended in most cases.

Give your agent this brain