How To Eject From Expo Managed Workflow to Bare?
Tags: reactnative, mobile, expo
Published: 2021-06-08 06:50:20

<!-- wp:heading -->
<h2>Introduction</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>If you are afraid to eject from Expo Managed Workflow to Bare Workflow, this article will help you a lot.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><a href="https://expo.io/" target="_blank" rel="noreferrer noopener nofollow">Expo</a> is a fantastic tool to develop React Native apps.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>There are two ways you can use Expo - <strong>managed</strong> and <strong>bare</strong> workflow. The Expo team recommends using the first option at the beginning of the road.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To start with the <strong>managed workflow</strong> what developers need to know is JavaScript and a few skills in React only. All the configuration is contained in one file - <strong>app.json</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>However, sometimes we encounter certain limitations and are forced to leave the managed workflow, but many developers seem to be afraid of taking this step.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>So, should they eject from Expo managed workflow?<br><br></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Why using Expo instead of starting with a plain React Native project?</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>First, <a href="https://pagepro.co/hire-expo-developers.html" target="_blank" rel="noreferrer noopener">Expo development</a> offers a lot of well-tested, consistent, and increasingly comprehensive libraries that give you access to the underlying native APIs. Additionally, the Expo team offers battle-tested modules that are constantly maintained by them. This is a great advantage, as developers can spend more time developing instead of doing painful configure.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Expo also offers many out of the box solutions such as <strong>OTA (Over The Air) </strong>updates and a push notification service.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Think of OTA - if you ever had a situation where you find typo mistakes or have to change some spacing by adding a few pixels in your app, and then you have to wait for Apple to approve a change, you'll appreciate OTA updates a lot - as all of those small changes will appear as soon as you run the publish command. It simply publishes new version of JavaScript application and updates without building standalone app and re-submitting it to the App Stores.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Expo also contains a <strong>push notification service</strong> out of the box. It is a very important feature to notify users about, for example, sales in shops, messages from friends or incoming purchases. All the troubleshootings with native device information and communicating with APNs or FCM are taken care of behind the scenes, so that you can treat iOS and Android notifications the same, saving yourself tons of time on the front-end, and back-end!</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Let’s have a look on other advantages Expo has over plain React Native projects.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Meet <strong>Expo CLI</strong> (command line interface) and <strong>Expo Dev Tools (Web UI) </strong>- things that allow developers to install packages, run, and easily manage projects. Later on you can run applications on different platforms (iOS, Android, Web) from <strong>dev tools</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Expo also contains a <strong>list of connected devices</strong> via <strong>QR code </strong>- enabling easy connection of physical devices. It is awesome as you can share your app with anyone, anywhere in the world while you're working through the <strong>Expo Go app</strong> (available on App/Play Store)!</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":5351,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="https://pagepro.co/blog/wp-content/uploads/2021/02/pasted-image-0-1024x593.png" alt="Expo managed workflow: Screenshot of Expo Go app" class="wp-image-5351"/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>When you change connection to <strong>tunnel mode</strong> and share your QR code with other people, they are able to run the app on their phones.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>It’s a very useful tool to work with designers, for instance. They can run the app on their phones, and whatever the developer will change in the code, it appears on their devices instantly.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The reason for that is applications are built and hosted on <strong>S3</strong>. Every change in code rebuilds the app on S3 and immediately updates the app on users devices.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Instead of having to sign up several external testers through App Store Connect, you can easily have them download the Expo Go app and have a working version on their phone.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The last thing I would like to mention is that Expo is automatically updating our React Native to a higher version, so we don’t have to do it on our own. And please, let those who never had a problem with the RN update raise their hands first.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>So with Expo,<strong> the update’s nightmare will finally disappear</strong>.<br><br></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>If you decide to use Expo</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>The Expo team suggested that we should start developing with <strong>managed workflow</strong> first.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>So, What is <strong>managed workflow</strong> actually?</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In documentation we can see:</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>“The managed workflow is kind of like Rails and Create React App, but for React Native.”.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Expo is really trying to manage as much of the complexity of building apps for you as it can, which is why they call it the managed workflow.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Developers that are using managed workflow don't have to use Xcode or Android Studio, so they just write JavaScript code and manage configuration through <strong>app.json</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Isn’t that fantastic?</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Building mobile apps just in JavaScript and all the configuration is managed by app.json file.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This is truly awesome, yet, just the same as everything that's awesome, ends quickly.<br><br></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Limitation of Expo managed workflow.</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Here’s the list:</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color"><strong>Not all iOS and Android APIs are available</strong></h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Some of the APIs are not available yet:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Bluetooth</li><li>WebRTC</li><li>In-App Purchases</li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color"><strong>The SDK doesn’t support all types of background code.</strong></h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>For now SDK supports only geolocation (including geofencing) and background fetch. You cannot do anything with audio, controls or handle push notifications in the background.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color"><strong>If you need to keep your app size extremely lean, the managed workflow may not be the best choice.</strong></h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p><strong>iOS app 20mb / Android 15 mb size.</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This is because "managed" includes a bunch of APIs - this lets you push over-the-air updates to use new APIs, but comes at the cost of binary size.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Some of the APIs that are included are tied to services that you may not be using - like Facebook Mobile SDK ,Google Mobile SDK - however, they offer many possibilities related to e.g. Auth.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color"><strong>Native libraries to integrate with proprietary services are usually not included in the SDK</strong></h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Avoid adding native modules to the SDK if they are tied to external, proprietary services — we can't add stuff to the SDK just because a few users need it. It increases the size of building and the expo team is starting to think of the broader userbase.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The only supported third-party push notification service is the Expo notification service.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color"><strong>The minimum supported OS versions are Android 5+ and iOS 10+</strong></h4>
<!-- /wp:heading -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color"><strong>Updates (JS and assets) for OTA updates and builds are size-limited</strong></h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Expo's current update service supports updates around 50 MiB.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>If you met any of the limitations outlined above, it’s probably time to eject from expo managed workflow and start with the bare workflow.<br><br></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>It’s about time to eject from Expo managed to the bare workflow</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Many JavaScript developers are <strong>concerned about ejecting</strong> from managed workflow.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>They are not sure if they can handle things related to native applications, but they must remember that <strong>fear makes things look twice as bad as they are!</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>After running the <strong>eject</strong> command in our project this is how the terminal looks like:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":5352,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="https://pagepro.co/blog/wp-content/uploads/2021/02/Zrzut-ekranu-2021-01-30-o-22.35.48.png" alt="developer's terminal after running an eject command" class="wp-image-5352"/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>It asks about the name for android package and iOS identifier. I leave it as default values.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>After the successful eject we got info like this below:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":5353,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="https://pagepro.co/blog/wp-content/uploads/2021/02/unnamed.png" alt="reply from the terminal" class="wp-image-5353"/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>We have already changed workflow mode from managed to bare.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Take a look at the file tree. Something new has appeared.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Two new directories:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><strong>Android</strong> - contains files that are responsible for the native part of android app.</li><li><strong>iOS</strong> - like in android directory, but that are responsible for iOS part.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p><strong>Index</strong> file is the entry point of our app and <strong>metro.config</strong> - a JavaScript bundler used to React Native apps.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":5354,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="https://pagepro.co/blog/wp-content/uploads/2021/02/index-file.png" alt="index file" class="wp-image-5354"/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>In the <strong>bare workflow</strong> we have full access to the underlying native projects and any native code. It's a "bare" native project with React Native and one or more packages from the Expo SDK installed.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In other words, anything that you can do in a native project is possible here.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>Minds that the configuration must be done on each native project rather than once with app.json</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Configuring app icons, launch screen, and so on must be configured in the native projects for each platform using the standard native tooling, rather than once using a simple JSON object.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>When you eject from the managed workflow, the app becomes a vanilla React Native app that includes all the Expo SDK APIs that you were using already (not more than that).<br><br></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Developing app in Bare Workflow</h2>
<!-- /wp:heading -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color">Run and build project</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Now we just have to run yarn ios or yarn android to start JavaScript bundler server and build the project binary. This requires also Xcode or Android Studio, depending on the platform.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color">Adding libraries from Expo SDK</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Pretty much the same as in managed workflow using expo install. Additional step is to run npx pod-install to install iOS native dependency. Some of the packages require a bit of additional work with adding stuff to info.plist - iOS or android manifest files.<br>After that, you just need to recompile the project for both platforms.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color">Adding own custom native code</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>The process looks pretty much like in any other React Native app. It is mostly depending on docs of these packages, but usually you need to add a bit of code to files in iOS and Android directories.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color">Developing with Expo Go app</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>You can still use the Expo Go app after the eject. When you have added a native code that client doesn’t support, you just need to add guards to prevent invoking native APIs when they aren’t available.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To achieve that you can use the Constants package from Expo SDK. That package includes information about apps run on Expo App Go.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Another way is to use special files with expo extension. For example, if we use a component that renders a Map and the map library isn’t supported by Expo, you can prepare another component called Map.expo.[js/json/ts/tsx] which will be rendered in the app if you run it by Expo Go. If you run apps in a traditional way, it will just render a correct Map component.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color">React Native for Web app on bare project</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Expo for web also works on bare projects. All you need to do here is to import one simple component into App.web.js to demonstrate it, and run expo start --web.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4,"textColor":"vivid-red"} -->
<h4 class="has-vivid-red-color has-text-color">Workflow comparison</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>As you can see the differences between those workflows are very small. We can still use most of the tools. On the Expo site in their Docs we can see a table with comparison.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":5355,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="https://pagepro.co/blog/wp-content/uploads/2021/02/Workflow-comparison.png" alt="A comparison of managed and bare Expo workflow" class="wp-image-5355"/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>So, as you can see, most things are covered. The only difference is, in managed workflow we write just in JavaScript, but we cannot add custom native code, nor manage native dependencies, or one of the things I mentioned above in managed limitations.<br><br></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>If you choose an Expo tool to develop the next React Native project and start in a managed workflow, you don’t need to be afraid to eject from it, if you feel you have to.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The differences between them aren’t as big and as scary as it may seem. We have access to Android and iOS native modules and all we have to do is some configuration on it instead of configuring all in app.json file.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>After the eject we can still use most of the things Expo gives us - Expo - SDK, CLI, Go App or OTA. So if the time to eject comes, don’t panic, <strong>bare flow is also fantastic, just like a managed way</strong>.</p>
<!-- /wp:paragraph -->