Expo SDK 41
By: Brent Vatne
Tags: iOS, Web, React Native, Android, Expo

Today we’re announcing the release of Expo SDK 41. SDK 41 includes React Native 0.63, the same version as in SDK 40. Thank you to everyone that helped with beta testing. Curious why we didn’t include the recently released React Native 0.64? Learn more.)

⚡️ Highlights

Android apps now target Android R (11 / SDK 30) . This comes with some significant changes for location permissions, media library (related to StorageAccessFramework), and constants. Please note that these changes also impact SDK <= 40 projects in Expo Go, but they will not impact SDK <= 40 standalone apps. Refer to expo.fyi/android-r for more information.

. This comes with some significant changes for location permissions, media library (related to StorageAccessFramework), and constants. Please note that these changes also impact SDK <= 40 projects in Expo Go, but they will not impact SDK <= 40 standalone apps. Refer to expo.fyi/android-r for more information. The recommended version of react-native-reanimated has been updated to v2. If you would like to use v2 features in your app, you need to add the Reanimated v2 Babel plugin. You can continue to use v1 features (eg: those used by React Navigation v5) without adding the new Babel plugin. Please note that if you use the new features from v2, you will not be able to use remote JS debugging in your app! If you use v2 APIs, JS debugging is only possible using Flipper and Hermes, which are not yet fully supported in the managed workflow. (We plan to investigate integrating Hermes during the next SDK cycle, but we don't currently expect to have it ready for SDK 42.)

If you would like to use v2 features in your app, you need to add the Reanimated v2 Babel plugin. You can continue to use v1 features (eg: those used by React Navigation v5) without adding the new Babel plugin. Please note that if you use the new features from v2, you will not be able to use remote JS debugging in your app! If you use v2 APIs, JS debugging is only possible using Flipper and Hermes, which are not yet fully supported in the managed workflow. (We plan to investigate integrating Hermes during the next SDK cycle, but we don't currently expect to have it ready for SDK 42.) lottie-react-native has been updated to the latest version (3.5.0) . Your existing animations should continue to work as before, but if you encounter any issues please file an issue and share the animation file.

. Your existing animations should continue to work as before, but if you encounter any issues please file an issue and share the animation file. The new version of react-native-screens (v3) “enables screens” by default. If you encounter any related issues, you can report the issue and opt out with enableScreens(false) . Be sure to update to the latest v4 patch release of React Navigation if you use v4.

If you encounter any related issues, you can report the issue and opt out with . Be sure to update to the latest v4 patch release of React Navigation if you use v4. Improvements were made across the SDK to ensure compatibility with EAS Build. A big part of this SDK has been making the necessary underlying changes to support EAS Build for managed projects. You can now use EAS Build with Expo managed apps to reduce the size of your standalone apps by up to 10x! Learn more about the latest EAS Build updates.

A big part of this SDK has been making the necessary underlying changes to support EAS Build for managed projects. You can now use EAS Build with Expo managed apps to reduce the size of your standalone apps by up to 10x! Learn more about the latest EAS Build updates. The expo package is now 93% smaller in production and better than ever. We've simplified the experience so the .expo extension is no longer needed (and so we removed it), and neither is the --target bare|managed flag — updates will run in either context provided the native runtime is compatible. We've improved consistency across the managed and bare workflow, removed legacy code, and improved tree-shaking on the package using @expo/metro-config .

We've simplified the experience so the extension is no longer needed (and so we removed it), and neither is the flag — updates will run in either context provided the native runtime is compatible. We've improved consistency across the managed and bare workflow, removed legacy code, and improved tree-shaking on the package using . To see the full list of new features and fixes, refer to the changelog!

🏡 Expo Go

We changed sign in to use expo-web-browser so we can leverage our existing web auth flow with two-factor-authentication.

so we can leverage our existing web auth flow with two-factor-authentication. You can now see teams and organizations that you are a part of in the Profile tab, and their associated projects show up in your recent projects below.

Notice the “Accounts & Organizations” section and the shared “Recent Projects” list below it.

🌐 Expo CLI

Integrated Developer Tools: Open the developer menu, inspect elements, and monitor performance all from the CLI. Just run expo start then press "m" to toggle the dev menu, and "shift+M" to toggle the performance monitor or element inspector across native apps.

It was either a heavily compressed but still 7mb gif or a YouTube video, so we went for the YouTube video.

Force Reloading: Shaking your devices every few minutes can get exhausting! Now you can reload connected phones, tablets, simulators, and browsers all by pressing “r” in the Terminal UI. This works across iOS, Android, web, and on physical devices.

Automatic TypeScript setup: Setting up TypeScript can be a pain, so we’ve completely automated it! Just create a blank tsconfig.json and run expo start , we'll take care of the rest! Learn more: "TypeScript" in the Expo docs.

Vastly better errors: No one likes errors — that’s why in SDK 41 we’ve refined them to be as concise, and useful as possible! We only surface the most relevant stack traces and point to exactly where the error or warning is. We’ve also improved source maps, and muted generated code traces.

Debug your config: The new expo config command enables you to view the evaluated results of app.config.js or app.json . You can use expo config —-type public to see the app manifest used in expo publish .

The new command enables you to view the evaluated results of or . You can use to see the app manifest used in . Better interactions with Apple Store Connect from your terminal: Faster, smarter authentication, better error handling, and — for the first time ever — get full insight into complex issues right from the console. Where other tools 401 , Expo CLI gives you links to resolve issues in seconds. Need to update your payment or accept a contract? Resolve in a couple clicks, and get back to developing incredible (or at least “good”) apps!

A terminal window showing information about a rejected request from App Store Connect due to an expired Developer Program membership.

The --config is flag deprecated . We suggest using app.config.js instead. The --config flag will continue to be supported for existing use cases for the foreseeable future, but it will not be supported in some situations in bare workflow projects, and it will also not be supported on EAS Build. Learn more: Migrating away from --config in Expo CLI.

. We suggest using instead. The flag will continue to be supported for existing use cases for the foreseeable future, but it will not be supported in some situations in bare workflow projects, and it will also not be supported on EAS Build. Learn more: Migrating away from --config in Expo CLI. The --target flag is deprecated for SDK 41+ . This was used to provide slightly different behavior when in a managed or bare app environment, but it ended up being tricky to use because updates published with the bare target could not run in Expo Go, and updates published with the managed target could not run in a bare app. We now do any necessary adjustments to accommodate the environment at runtime, so an update bundle will work in either context, provided that the native runtime is compatible with the update.

. This was used to provide slightly different behavior when in a managed or bare app environment, but it ended up being tricky to use because updates published with the target could not run in Expo Go, and updates published with the target could not run in a bare app. We now do any necessary adjustments to accommodate the environment at runtime, so an update bundle will work in either context, provided that the native runtime is compatible with the update. Versioned Metro Config: Rather than adding @expo/metro-config to your package.json , you can now import it through the expo package with the vendored expo/metro-config import. This ensures that your project is always using a compatible version of the package. Learn More: Customizing Metro.

Rather than adding to your , you can now import it through the package with the vendored import. This ensures that your project is always using a compatible version of the package. Learn More: Customizing Metro. Introducing Config Plugins (beta): Config plugins are an important step towards making it possible for library authors to make their native modules part of the Expo ecosystem. This system is in beta, with a more stable release planned for SDK 42. Learn more: Config Plugins.

🏗 Deprecations, renamings, and removals

Deprecated globals have been removed from the expo package.

As a result, expo-linear-gradient , expo-linking , expo-location , expo-permissions , and expo-sqlite are no longer automatically installed in every project by default as dependencies of expo . If you were depending on global.expo.LinearGradient or similar, please install the respective package and import the API from there instead, eg: import { LinearGradient } from 'expo-linear-gradient'; . Refer to expo.fyi/deprecated-globals for more information.

Files with the .expo.* extension (eg: MyComponent.expo.js ) are no longer recognized as source files.

If your project source code or dependencies include any files with the .expo.* extension, expo-cli will let you know when you upgrade. Refer to expo.fyi/expo-extension-migration for more information.

We thought the .expo file extension was neat but it ended up not being necessary or particularly useful, and simplicity wins over neat things.

expo-permissions has been deprecated in favor of module-specific permissions methods

You should migrate from using Permissions.askAsync and Permissions.getAsync to the permissions methods exported by modules that require the permissions. For example: you should replace calls to Permissions.askAsync(Permissions.CAMERA) with Camera.requestPermissionsAsync() . There shouldn’t be two ways to do an identical thing in a single SDK, and so we picked our preferred approach and are consolidating around it.

@react-native-community/async-storage is now @react-native-async-storage/async-storage

AsyncStorage is next in the packages that are gradually migrating out of the @react-native-community scope on npm (more context on why this is happening available here). We will take care of switching the packages in your dependencies in package.json when you run expo upgrade , but after that you will need to either manually update your imports in your source code, or run npx expo-codemod sdk41-async-storage [your-source-directory] to update it automatically.

Along with this superficial change in package names comes a fix for an issue that occurs when ejecting your project; more information in this issue and these pull requests.

@expo/metro-config is now vendored by the expo package.

If your metro.config.js uses @expo/metro-config , you should switch over to importing it from the expo package instead.

Remove @expo/metro-config from your package.json dependencies and change your import in. metro.config.js from @expo/metro-config to expo/metro-config . Learn more: Customizing Metro.

Legacy Notifications API has been removed

The legacy Notifications library (imported from the expo package) has been deprecated since SDK 38, and is now fully removed in SDK 41. If you’re still relying on this package, you should upgrade to expo-notifications , which has plenty of improvements and additional features. Learn more: How to migrate from Expo's LegacyNotifications to the new expo-notifications library.

👋 iOS 10 support has been dropped — Expo SDK 41 supports iOS 11+.

More information on this from our SDK 40 release notes:

iOS 10 is the last version of iOS that still supports 32-bit simulator builds (x86), and to keep Expo npm packages smaller, we plan to publish only 64-bit pre-build binaries for simulators (x64 and arm64). This has been past due — the last time we dropped an iOS version was over two years ago, when we dropped support for iOS 9 in September 2018. Apple no longer reports usage statistics for iOS 10 directly, but you can get a rough idea from reading the App Store — iOS and iPadOS usage table — 6% of all devices use iOS 11 or lower at the time of writing.

🟢 Node 10 support will be dropped soon from Expo CLI

It’s not that we have anything against the number 10, but Node 10 is about to be replaced by Node 12 as the Maintenance LTS release.

🧹 Dropped SDK 37; will drop SDK 38 next release

We routinely drop SDK versions that have low usage in order to reduce the number of versions we need to support. This release sees the end of life for SDK 37. As usual, your standalone apps built with SDK 37 will continue to work; however, SDK 37 projects will no longer work within the latest version of Expo Go. If you want to re-run expo build , then you’ll need to upgrade from SDK 37, preferably to SDK 41 so you won’t need to update again for a while (and also because each Expo version is better than the last!).

Our next release is planned for June/July 2021 and, at that time, we’ll be dropping support for SDK 38. If your project is running on SDK 38, consider upgrading to a newer version in the coming months.

➡️ Upgrading your app

Managed workflow

Here’s how to upgrade your app to Expo SDK 41 from 40:

Update to the latest version of Expo CLI: npm i -g expo-cli . expo-cli@4.4.1 or greater is required.

. or greater is required. Run expo upgrade in your project directory.

in your project directory. If you are using react-navigation v4, please be sure to update to the latest v4 patch release. This is required due to changes in the version of react-native-screens included in SDK 41.

v4, please be sure to update to the latest v4 patch release. This is required due to changes in the version of included in SDK 41. Refer to the “Deprecations, renamings, and removals” section above for breaking changes that are most likely to impact your app.

Make sure to check the changelog for all other breaking changes!

Update the Expo app on your phones from the App Store / Google Play. expo-cli will automatically update your apps in simulators if you delete the existing apps, or you can run expo client:install:ios and expo client:install:android .

will automatically update your apps in simulators if you delete the existing apps, or you can run and . If you built a standalone app previously, remember that you’ll need to create a new build in order to update the SDK version. Run expo build:ios and/or expo build:android when you are ready to do a new build for submission to stores.

Bare workflow

The Bare workflow lets you operate independently of the Expo SDK cycle, updating RN versions and versions of individual Expo packages however and whenever you want. However, if you do stick roughly to Expo SDK versions, these steps will help you to upgrade to Expo SDK 41 from 40: