HomeGuidesReferenceLearn
ArchiveExpo SnackDiscord and ForumsNewsletter

EAS Update with a local build

Learn how to use EAS Update directly with a local build environment.


In this step-by-step guide, you'll create a new Expo app, run it in your local development environment, publish an update, and show that the app downloads and runs the update when restarted. It also details some of the app config properties used in EAS Update and their functions.

1

Install the latest EAS CLI

EAS CLI is the command-line app that you will use to interact with EAS services from your terminal. To install it, run the command:

Terminal
npm install --global eas-cli

You can also use the above command to check if a new version of EAS CLI is available. We encourage you to always stay up to date with the latest version.

We recommend using npm instead of yarn for global package installations. You may alternatively use npx eas-cli@latest. Remember to use that instead of eas whenever it's called for in the documentation.

2

Create a project

Create a project by running:

Terminal
npx create-expo-app

3

Configure your project

To configure your project, run the following commands in the order they are specified:

Terminal
# Install the latest `expo-updates` library
npx expo install expo-updates

# Initialize the app in EAS
eas init

# Initialize your project with EAS Update
eas update:configure

Inside the app config, make changes to use runtimeVersion property with a fixed value and to add a request header that the app will use to specify a channel when downloading updates from EAS.

app.json
  "expo": {
    %%placeholder-start%%... your existing configuration %%placeholder-end%%
    "updates": {
      %%placeholder-start%%... %%placeholder-end%%
      "requestHeaders": {
        "expo-channel-name": "main"
      }
      %%placeholder-start%%... %%placeholder-end%%
    }
    "runtimeVersion": "1.0.0",
    %%placeholder-start%%... %%placeholder-end%%
  }

In the introduction guide, the channel name is set by EAS Build and is different for various build profiles. Since this is a local build, it is necessary to set this request header explicitly in the app config.

4

Run prebuild

Prebuild runs automatically when executing npx expo run:android or npx expo run:ios. However, we want to call this step out separately in this guide. From SDK 48 and above, this step adds our desired request headers to AndroidManifest.xml and Expo.plist in the Android and iOS builds.

Terminal
# Run prebuild to install and configure the android and ios directories, and install CocoaPods for iOS.
npx expo prebuild

After running the above, inspect android/app/src/main/AndroidManifest.xml and iOS/<your project name>/Supporting/Expo.plist to see the added changes.

Expo.plist
%%placeholder-start%%... Existing configuration %%placeholder-end%%
  <key>EXUpdatesRequestHeaders</key>
  <dict>
    <key>expo-channel-name</key>
    <string>main</string>
  </dict>
%%placeholder-start%%... Existing configuration %%placeholder-end%%
AndroidManifest.xml
%%placeholder-start%%... Existing configuration %%placeholder-end%%
  <meta-data android:name="expo.modules.updates.UPDATES_CONFIGURATION_REQUEST_HEADERS_KEY" android:value="{&quot;expo-channel-name&quot;:&quot;main&quot;}"/>
%%placeholder-start%%... Existing configuration %%placeholder-end%%

In SDK 48 and later, the requestHeaders property from the app config is used to automatically add these lines to the native files.

5

Build the project

Run the following commands to get the app running on Android or iOS.

Terminal
# Android: Build and run the app on a local Android Emulator
npx expo run:android --variant release

# iOS: Build and run the app on a local iOS Simulator.
npx expo run:ios --configuration Release

We build the release version of the app, not the debug version. By default, a debug build expects to connect to a local React Native packager to load the application bundle and will not connect to the EAS Update service.

It is possible to create a native debug build that will connect to the EAS Update service and allow debugging of native code. See Testing updates with a debug build section for the required changes.

6

Make the modifications below to App.js so that the app uses the Updates API to show if it has downloaded and run an update.

App.js
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import * as Updates from 'expo-updates';

export default function App() {
  const runTypeMessage = Updates.isEmbeddedLaunch
  ? 'This app is running from built-in code'
  : 'This app is running an update';
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <Text>{runTypeMessage}</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

Then build and run the app again:

Terminal
# Android: Build and run the app on a local Android Emulator
npx expo run:android --variant release

# iOS: Build and run the app on a local iOS Simulator.
npx expo run:ios --configuration Release

The app should appear as in the screenshot below.

7

Publish an update

Now we're ready to publish an update that will include our changes.

After optionally making additional changes to App.js, publish an update with the following command:

Terminal
eas update

Running the command will prompt the following:

  • For the branch to publish on. Select the default branch: main.
  • For entering an update message. Select the default Initial commit message or type in a custom message.

Once the update is built and uploaded to EAS and the command completes, force close and reopen your app up to two times to download and view the update.

The app should now appear as shown in the screenshot below:

Testing updates with a debug build of your app

It is possible to create a debug build that will load updates from EAS instead of loading from a React Native packager.

To do this for the above app, modify step 4 above as follows:

Terminal
# Set the environment variable needed for native debug builds
export EX_UPDATES_NATIVE_DEBUG=1

# Run prebuild to install and configure the android and ios directories, and install CocoaPods for iOS.
npx expo prebuild

# iOS: Modify the application project so that the application JavaScript
# is bundled into the app for both debug and release builds.
sed -i '' 's/SKIP_BUNDLING/FORCE_BUNDLING/g;' ios/<project name>.xcodeproj/project.pbxproj

# iOS: Build and run the app on a local iOS Simulator.
npx expo run:ios --configuration Debug

# Android: Build and run the app on a local Android Emulator
npx expo run:android --variant debug

The resulting app will be fully debuggable with Xcode or Android Studio, but will work with the EAS Update service the same way as a release build, and will not connect to a local packager.