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

build-reference/configuration

160 notes in this subject, read out of this brain and free to use. This is page 1 of 3.

No additional configuration steps for React Native projects

For existing React Native projects, there are no additional configuration steps beyond the basic eas.json creation. The configuration process is complete after initialization.

app.json configuration for Expo projects

For Expo projects, if you haven't configured your app.json with android.package and/or ios.bundleIdentifier yet, EAS CLI will prompt you to specify them when you create your first build. The android.package will be used as the Android application ID to identify your app on the Google Play Store, and ios.bundleIdentifier will be used to identify your app on the Apple App Store.

eas.json differs for existing React Native projects

The default eas.json configuration created by EAS CLI will look different for existing React Native projects compared to Expo projects.

Select platforms during initial configuration

When running EAS CLI configuration for the first time, you are prompted to select the platform(s) you want to configure. You can configure just one platform initially and configure other platforms later if you change your mind.

eas build:configure command initializes EAS project

When you run `eas build:configure` (or `eas build` if the project is not yet configured), EAS CLI performs a configuration process that initializes your EAS project. The same configuration steps execute whether you use `eas build:configure` or `eas build` on an unconfigured project.

.easignore example with common directories

A .easignore file should copy content from .gitignore and add files unnecessary for the build process. Common entries include /docs for documentation, /android and /ios for native directories (if using EAS Build), and /coverage for test coverage reports. If your project does not contain android and ios directories, EAS Build will run Prebuild to generate these native directories before compilation.

.easignore file purpose and location

A .easignore file defines which files EAS should ignore when uploading your project to EAS Build servers. The .easignore file is created in the root of your project.

Including files not in source control with ! prefix

You can use the .easignore file to include files with your EAS Build upload that are not committed to source control by adding them with a ! prefix. This is useful for custom scripts that generate temporary files needed for the build process. The ! prefixed file should be last in the .easignore file so it takes precedence over any prior rules that would ignore it.

.easignore example with negation pattern

To upload a file not in source control to EAS Build, add it to the .easignore file with a ! prefix. Example: after copying .gitignore contents and ignoring directories like /android and /ios, you can add !temp_file.json to include a file that would otherwise be ignored.

Ignoring unnecessary files reduces archive size and upload time

Ignoring unnecessary files can help reduce your app's archive size and upload time during EAS Build.

Step 2: Use eas-build-pre-install npm hook for submodule initialization

Add an eas-build-pre-install npm hook to check out submodules. The hook script should restore the private key from an environment variable, generate the public key, add the git provider to known hosts, and run git submodule update --init.

Step 1: Create secret with base64 encoded SSH key for submodule access

Create a secret with a base64 encoded private SSH key that has permission to access submodule repositories. This secret will be used during the EAS Build process.

When to initialize submodules on EAS Build

You will need to initialize submodules on EAS Build builder to avoid uploading empty directories if you are building on CI, have cli.requireCommit set to true in eas.json, or have a submodule in a private repository.

Git submodules uploading during default VCS workflow

When using the default Version Control Systems (VCS) workflow in EAS Build, the content of your working directory is uploaded to EAS Build as it is, including the content of Git submodules.

Shared user cache isolation risk

When a single user-actor is shared between multiple people (such as when using access tokens or triggering builds from GitHub Actions), user-scoped cache rules still apply. This means builds operating under that shared account will no longer have isolated caches and run the risk of sharing unintended artifacts. To avoid this, do not restore cache for production builds under a shared user, and have designated jobs to only save clean, new caches.

Cache key matching behavior with restore keys

When restoring a cache, the cache system searches in this sequence: first for an exact match to the cache key (automatically generated or explicitly provided), then checks restore_keys for prefix matches. If there is an exact match, it is a direct cache hit and restored immediately. If there is a partial match or match from restore_keys, the cache is restored but may not perform as effectively. The cache with the most recent creation date is used among matching restore keys.

Cache saving does not become exclusive with EAS_SAVE_CACHE

Setting EAS_SAVE_CACHE to "1" does not make cache saving exclusive to a specific job. Other jobs with the same environment variable can still save and overwrite the cache.

EAS Workflows ccache steps for iOS

For EAS Workflows iOS builds, use eas/restore_build_cache and eas/save_build_cache steps in your workflow. The commented example shows you can also use eas/restore_cache with a custom key pattern like ios-ccache-${{ hashFiles('yarn.lock') }} and restore_keys like ios, with path set to /Users/expo/Library/Caches/ccache for other caching purposes.

Custom build ccache cache steps

In custom builds where you manage the build steps, add eas/restore_build_cache and eas/save_build_cache to enable ccache cache. The cache key uses a hash of the package manager lock file to create a unique key based on your dependencies. When dependencies change, a new cache is created while still allowing fallback to previous caches using restore_keys.

EAS Workflows ccache steps for Android

For EAS Workflows Android builds, use eas/restore_build_cache and eas/save_build_cache steps in your workflow. The commented example shows you can also use eas/restore_cache with a custom key pattern like android-ccache-${{ hashFiles('yarn.lock') }} and restore_keys like android, with path set to /home/expo/.cache/ccache for other caching purposes.

Dependency caching limitations

Android builds cache npm and Maven dependencies locally. iOS builds cache npm dependencies locally and CocoaPods artifacts from a cache server. Intermediate artifacts like node_modules directories are not cached and restored based on package-lock.json or yarn.lock, but if committed to the Git repository they will be uploaded to build servers.

Resource class option for high-memory builds

If your build process requires a significant amount of memory, consider using a 'large' resource class in the eas.json configuration. See Android-specific and iOS-specific resource class options in the build-reference/infrastructure documentation.

Platform support for local EAS builds

macOS and Linux are officially supported for local EAS builds. Windows is not officially supported, though WSL (Windows Subsystem for Linux) can be used without official testing or support.

Difference between local builds and local compilation

Local EAS builds using `eas build --local` are different from local app compilation for development. To compile locally for development, use `npx expo run:android` or `npx expo run:ios` commands instead. With Continuous Native Generation, you can run prebuild to generate android and ios directories, then open them in respective IDEs. To create a production build locally, use dedicated guides that cover the process differently from creating a build on the cloud with EAS Build.

Local builds limitations

Local builds have the following limitations: you can only build for a specific platform (the 'all' option is disabled); customizing versions of software is not supported, and fields node, yarn, fastlane, cocoapods, ndk, and image in eas.json are ignored; caching is not supported; EAS environment variables with 'Secret' visibility are not supported (set them in your local environment instead); you are responsible for ensuring the environment has all necessary tools installed including Node.js/Yarn/npm, fastlane (iOS only), CocoaPods (iOS only), and Android SDK and NDK.

Environment variables for local build debugging

Three environment variables control local build behavior: EAS_LOCAL_BUILD_SKIP_CLEANUP=1 disables cleanup of the working directory after the build process finishes; EAS_LOCAL_BUILD_WORKINGDIR specifies the working directory for the build process (defaults to a platform-dependent location in /tmp directory); EAS_LOCAL_BUILD_ARTIFACTS_DIR specifies where artifacts are copied after a successful build (defaults to the current directory). For iOS builds using EAS_LOCAL_BUILD_SKIP_CLEANUP and EAS_LOCAL_BUILD_WORKINGDIR, you can inspect the logs subdirectory of the working directory to read Xcode logs.

Node script example for platform-specific hooks

You can use Node.js to run platform-specific scripts by checking the EAS_BUILD_PLATFORM environment variable via process.env. Example: if (process.env.EAS_BUILD_PLATFORM === 'android') { console.log('Run commands for Android builds here'); } else if (process.env.EAS_BUILD_PLATFORM === 'ios') { console.log('Run commands for iOS builds here'); }

Shell script example for platform-specific hooks

You can use bash conditionals to run commands only for specific platforms. The condition checks if $EAS_BUILD_PLATFORM equals 'android' or 'ios'. Example: if [[ "$EAS_BUILD_PLATFORM" == "android" ]]; then echo "Run commands for Android builds here"; elif [[ "$EAS_BUILD_PLATFORM" == "ios" ]]; then echo "Run commands for iOS builds here"; fi

Platform-specific hook behavior with EAS_BUILD_PLATFORM

To run a script or part of a script only for Android or iOS builds, you can check the EAS_BUILD_PLATFORM environment variable within your script. The value is either 'android' or 'ios'. This allows you to fork behavior depending on the platform.

macOS Sonoma 14.4 Xcode 15.3 iOS image

Image name: macos-sonoma-14.4-xcode-15.3. macOS Sonoma 14.4.1, Xcode 15.3 (15E204a), Node.js 18.18.0, Bun 1.0.35, Yarn 1.22.21, pnpm 8.14.1, npm 9.8.1, fastlane 2.219.0, CocoaPods 1.14.3, Ruby 2.7, node-gyp 10.0.1.

macOS Sequoia 15.3 Xcode 16.2 SDK 52 iOS image

Image name: macos-sequoia-15.3-xcode-16.2 (alias: sdk-52). macOS Sequoia 15.3, Xcode 16.2 (16C5032a), Node.js 20.18.3, Bun 1.2.4, Yarn 1.22.22, pnpm 9.15.5, npm 9.8.1, fastlane 2.226.0, CocoaPods 1.16.2, Ruby 3.2, node-gyp 11.1.0.

Supported Xcode versions policy

Expo aims to support all stable Xcode releases that allow you to submit your app to the App Store Connect when used during the build process. This usually means supporting the latest stable Xcode version and the previous one until Apple introduces a new minimal Xcode version requirement.

macOS Tahoe 26.4 Xcode 26.4 SDK 56 iOS image

Image name: macos-tahoe-26.4-xcode-26.4 (alias: sdk-56). macOS Tahoe 26.4.1, Xcode 26.4 (17E202), Node.js 22.22.2, Bun 1.3.13, Yarn 1.22.22, pnpm 10.33.3, npm 10.9.4, fastlane 2.233.1, CocoaPods 1.16.2, Ruby 3.2, node-gyp 12.3.0, Maestro 2.5.1.

iOS build environment configuration

iOS builds include npm cache and CocoaPods cache. Global npm configuration uses registry=http://npm.caches.eas-build.internal. Global Yarn configuration in ~/.yarnrc.yml sets npmRegistryServer to http://npm.caches.eas-build.internal, unsafeHttpWhitelist to '*', and enableImmutableInstalls to false.

iOS build VM isolation and fresh instances

iOS builder VMs run on Mac mini hosts in an isolated environment. Every build gets its own fresh macOS VM.

Build image consistency guarantees

Using a specific image name guarantees a consistent environment with only minor updates. Using the 'auto' alias selects the build image based on project configuration, Expo SDK version, and React Native version. You can check what image is used for a build in the Spin up build environment build logs section.

Linux and macOS build server hosting

Linux runners are hosted in Google Cloud Platform. macOS runners are hosted in the Expo's own macOS cloud.

macOS Sequoia 15.4 Xcode 16.3 iOS image

Image name: macos-sequoia-15.4-xcode-16.3. macOS Sequoia 15.4.1, Xcode 16.3 (16E140), Node.js 20.19.1, Bun 1.2.11, Yarn 1.22.22, pnpm 9.15.9, npm 9.8.1, fastlane 2.227.1, CocoaPods 1.16.2, Ruby 3.2, node-gyp 11.2.0, jq 1.7.1, Azul Zulu JDK 17.58.21 (OpenJDK 17.0.15), Git 2.49.0, Git LFS 3.6.1, applesimutils 0.9.10, idb-companion 1.1.8.

Builder IP addresses file location

A list of the IP addresses of the build servers is available at https://expo.dev/eas-build-worker-ips.txt. The list includes Last-Modified and Expires ISO 8601 timestamps that specify when the list was last updated and when we commit to not change it.

Manual .npmrc update when file exists

If a .npmrc file already exists in your project's root directory, EAS Build will not automatically create one even when NPM_TOKEN is available. You must update the existing .npmrc file manually to include the authentication token configuration.

.npmrc configuration for both npm packages and private registry

To install dependencies from both npm private packages and a private registry, create a .npmrc in the project's root directory with: //registry.npmjs.org/:_authToken=${NPM_TOKEN}, @johndoe:registry=https://registry.npmjs.org/, and registry=https://registry.johndoe.com/. This example uses a scoped package under @johndoe namespace pointing to npm registry while the default registry points to the private registry.

Repack CLI arguments reference

Usage: @expo/repack-app [options] [project-root]. Argument: [project-root] - Path to the project root. Defaults to the current working directory.

Standalone repack CLI basic syntax

Run repack commands from your project's root directory. At minimum, --platform and --source-app are required. The tool runs npx expo export:embed under the hood to produce a fresh JS bundle, swaps it into the source binary, and writes the output artifact. The output format always matches the --source-app input: an APK input produces an APK, an IPA produces an IPA, and a .app bundle produces a .app bundle.

Repack prerequisites

To use repack, you need an existing build artifact produced from your Expo project: an APK for Android, or an IPA or .app bundle for iOS. Signing credentials are optional but required if the repacked artifact needs to be installable on a device.

Metro bundler JavaScript error example

When a build fails due to a JavaScript build error, you will see a message like 'Metro encountered an error: Unable to resolve module ./src/Routes from /Users/expo/workingdir/build/App.js'. This means the app is importing a module that is not found, which could be due to filename case differences in Git versus the developer's filesystem, or because the imported path was accidentally excluded in .gitignore.

Fresh clone testing for build differences

If an app builds locally but not on EAS Build, do a fresh git clone of the project to a new directory and get it running, ideally on a different machine. Pay attention to each step needed and verify that those steps are also configured for EAS Build.

Information to share when asking for troubleshooting help

When asking for troubleshooting help, share: a link to your build page (can be accessed by team or Expo employees, take a screenshot if sharing publicly, or email secure@expo.dev for private sharing; omit if performing local build with eas build --local); error logs related to build or runtime error; and a minimal reproducible example or link to the repository so other developers can reproduce the issue. Be clear, precise, and helpful.

Build failure vs runtime error distinction

There are two main ways something can go wrong: the build fails, or the build succeeds but the app encounters a runtime error such as crashing or hanging when run.

Local build commands for different package managers

To locally compile and run apps in release mode: for npm: 'npx expo run:android --variant release' and 'npx expo run:ios --configuration Release'; for yarn: 'yarn expo run:android --variant release' and 'yarn expo run:ios --configuration Release'; for pnpm: 'pnpm expo run:android --variant release' and 'pnpm expo run:ios --configuration Release'; for bun: 'bun expo run:android --variant release' and 'bun expo run:ios --configuration Release'.

Test local release builds with expo run commands

Verify that a project builds on the local machine with npx expo run:android and npx expo run:ios commands, with variant/configuration flags set to release to most faithfully reproduce what executes on EAS Build. For Android use '--variant release' flag, for iOS use '--configuration Release' flag.

Local build testing conditions for EAS Build success

If a project builds and runs locally in release mode, it will also build on EAS Build provided that: relevant build tool versions (Xcode, Node.js, npm, Yarn) are the same in both environments; relevant environment variables are the same in both environments; and the archive uploaded to EAS Build includes the same relevant source files.

Build phase change indicators in compare view

When comparing builds, indicators show what changed between two builds within each phase: 'Changed (X lines)' means the phase ran in both builds but produced different output; '+ Added' means the phase exists only in the comparison build (the original build failed before reaching it); '- Removed' means the phase exists only in the original build.

Solutions for .gitignore file resolution errors

To resolve 'None of these files exist' errors when importing gitignored files: remove the import statement if it is outdated or unused; remove files or directories Metro could not resolve from .gitignore (but this poses security risk for sensitive information); encode the file with base64 and create it in an EAS Build hook; or refactor source code to avoid importing sensitive files on the client side and use environment variables or backend services instead.

CNG prebuild cleanup after troubleshooting

If using Continuous Native Generation (CNG), the expo run commands will run npx expo prebuild to generate native projects to compile them. After troubleshooting, you likely want to clean up the changes made by prebuild unless you want to start managing these projects directly instead of generating them on demand.

Out-of-memory errors from large bundle sizes

If a build fails with 'Gradle build daemon disappeared unexpectedly (it may have been killed or may have crashed)' in Gradle logs, the Node process responsible for bundling the app JavaScript was killed. This often indicates the app bundle is extremely large, or large text files are treated as source code. To determine bundle size and see a breakdown of where size comes from, use Expo Atlas. To increase memory limits on EAS Build builders, use the 'large' resource class in eas.json.

stderr log entries may not indicate actual errors

It is common to see log entries prefixed with [stderr], but this does not necessarily mean those logs point to errors. CLI tools often use stderr to output warnings and other diagnostics.

Finding build error logs on build details page

Go to the build details page on the build dashboard and expand any failed build phases by clicking on them. Often, the earliest phase with errors will contain the most useful information, and any subsequent failed phase will have cascaded from the first.

Troubleshooting checklist for local vs EAS Build discrepancies

If builds succeed locally but fail on EAS Build: check that environment variables are properly configured; verify that versions of Node.js, npm, Yarn, Xcode, Java, and other tools are the same in both environments; ensure that the archive uploaded to EAS Build includes the same relevant source files.

CI environment variables for App Store Connect API

To use `--refresh-ad-hoc-provisioning-profile` in CI, provide an App Store Connect API key through environment variables: `EXPO_ASC_API_KEY_PATH`, `EXPO_ASC_KEY_ID`, and `EXPO_ASC_ISSUER_ID`, or store the key in EAS for submissions on the project.

Internal distribution CI automation with --non-interactive

Internal distribution builds can be run non-interactively in CI with the `--non-interactive` flag.

Give your agent this brain