Eas and Expo workflow

No need to “eject” when you’ve got EAS + Managed Workflow

image

Phil Lucks

·

Follow

6 min read

·

Feb 16, 2023

Photo by Pablo García Saldaña on Unsplash

image

How to run custom dependencies without ejecting or prebuilding

Because, when the docs make it unclear, you start making your own path.

There’s a section in the Expo Docs that says:

We highly recommend using prebuild for the reasons listed in the pitch section, but the system is fully optional and you can stop using it at any time.

I read this as a sign: if I want to replicate the build “locally” that would appear on EAS, then prebuild it on my machine to make sure there’s no errors before the pipeline takes a stab at it. This also would help if I ever need to install a dependency that is supported by Expo in terms of running on Expo Go with no additional configurations.

It made sense at the time and my coworker’s didn’t object. And I might have been the only person to take this step anyway. We (as in my team) are all n00bs in mobile development world, and every day I think we learn something new about this Expo ecosystem.

Fast Forward 6 months and we’ve released our Beta on Test Flight. All is going swimmingly in terms of getting the app build ahead of schedule. And then crossed the threshold of functionality which everyone knew was coming, but we didn’t know what it would mean until we got there.

We need to compress images & videos before sending to the backend.

We find a package which seems to work well: react-native-compressor. The docs seem to support my original interpretation of prebuild :

Finally, compile the mods: expo prebuild

Except it didn’t go as planned for the team. Everyone now HAD TO run prebuild and it was causing many problems: somehow only I was able to get a successful build running npx expo prebuild command.

My manager was suggesting looking at EAS logs, which show prebuild running. It was suggested that we need to fix the machine to handle it better. It was suggested to manually update CocoaPods. It was suggested we didn’t need to use prebuild or anything special at all.

My other teammate was just having failures and was in between the crossfire of suggestions.

image

I was flummoxed.

Side note: instead of going back & forth on Slack, hop on a call.

There had to be something we were missing.

I finally found an active Expo community in their Discord Channel and started asking the question:

If I want to run an NPM package, which is not supported in Expo, what is the way to do it, without ejecting & without prebuild?

Learn EAS + Managed workflow was the response. Ok..the Expo docs for me didn’t make it clear for me on all the bits & pieces, so without further ado, here is what I found:

Say you need a 3rd party dependency added to your project, such as video compression. This doesn’t work “out of the box”, and you’ll need a way to build your app.

As it turns out, “prebuild” changes your project from Managed Workflow to Bare Workflow. You almost certainly do not want to be in Bare Workflow. You can add packages with “native bits” if you are using EAS Build + Managed Workflow.

Your Expo/RN app is really 2 major parts:
  • the “native client”
  • the “JavaScript/React bundle”

eas build is used to build the "native client".

Each time you modify your project that affects the “native bits” (new NPMs, changes to app.json/app.config.js) then you would run your eas build to rebuild the "custom native client". With the "custom native client", if you include expo-dev-client, you get the same developer experience (e.g. hot module reload, integration with expo start) that you get with Expo Go.

The “native client’ is the thing you install on your mobile device. It has its own icon, splash screen, and app name. It also happens to start up a JS engine and exposes native APIs to that JS engine. Once the JS engine starts up, it loads the “JS/React bundle”. And, if you have the expo-dev-client as part of the "native client", it will reload the "JS/React bundle" when changes are made to it via expo start --dev-client

Anything you read that is more than, say, 6 months old w.r.t. RN and Expo…..use a healthy amount of skepticism. Anything more than 9 months old is likely wrong (now).

So, what actually is getting built?

The closest comparison I can come up with is: think of the image from EAS being like a Docker image. All the necessary modules exist in an isolated environment. This way you can focus on the coding of features in JS/TS.

You can still have a proper development experience, such as debugging and MHR, combining EAS + Expo Managed workflow.

To get started

  • Install the expo-dev-client and add it to your app.
  • Add a development profile to your eas.json such as
// for development simulator builds with Native Module packages
    "development": {
      "extends": "staging",
      "distribution": "internal",
      "developmentClient": true,
      "ios": {
        "simulator": true
      }
    },
// for development device builds with Native Module packages
    "development-device": {
      "extends": "staging",
      "developmentClient": true,
      "distribution": "internal"
    }
  • Add some new npm script to replace expo start, such as:
"debug": "open 'rndebugger://set-debugger-loc?host=localhost&port=19000'",
"debug.eas": "open 'rndebugger://set-debugger-loc?host=localhost&port=8081'",
"eas:build.dev.sim": "eas build --profile development --platform ios",
"eas:build.dev.device": "eas build --profile development-device --platform ios",
"eas:dev": "npx expo start --dev-client"

Developing on Simulator

  • Run yarn eas:build.dev.sim to kick off a build. This will generate a build on EAS which can be run on your simulator. Once it's completed, download the image from EAS.

Auto run your image in the Simulator

image

Developing on Physical Device

  • Run eas:build.dev.device to kick off a build. This will generate a build on EAS, resulting in a QR code.
  • Once you have the file, run yarn eas:dev start the server.
  • Use the device camera to scan the QR code and follow the instructions to install the app.
  • NOTE: if you’re having trouble getting the app running on an iOS simulator, manually start the simulator via: Xcode -> Open Developer Tool -> Simulator prior to running yarn ios.

What about starting a new branch?

If your project doesn’t automatically generate an image for you on each merge to develop, you’ll possible to kick off a build.

So far, when I have started a new branch, I actually have not had to, but I am prepared to such as switching between older branches.

When do I need to run EAS build?

  • When you’re adding a native module or something that edits the compiler/build via eas.json or app.config.
  • you have to rebuild the “client” whenever you make a change to the “native bits” (new NPMs, updates to app.json/app.config.js). But other than that, most of your coding will be on the JS code and for that you don’t need to rebuild the client app.

Small Print — as of 2/10/23, this has not been tested with Android

Source of information came from the Expo Discord conversation with @Greg Fenton , @Alan Hughes, both of whom are much more knowledgeable about Expo than the author of this post. Thank you both!