Learn about the changes, how to try it out, and how to give feedback.
MAY 2, 2024
By Chris Jensen
EAS Build is used by thousands of developers to build their apps on a daily basis. Some of these developers experience friction when they try to build a project via EAS Build, only for it to fail quickly for a variety of reasons, such as invalid configurations or minor code errors. This can be a frustrating experience, and doubly so when these failed builds cost developers money.
In an effort to continuously improve the Expo developer experience, we're happy to announce that from May 1, 2024, these builds will no longer be billed for or count against your monthly quota if you are on a Free plan. We define a "fast-failed build" as one that fails within 3 minutes. Each account will get a maximum of 10 of these waived each month.
APR 24, 2024
The SDK 51 beta period begins today and will last approximately one week. The beta is an opportunity for developers to test out the SDK and ensure that the new release does not introduce any regressions for their particular systems and app configurations. We're also hosting office hours for those of you interested in helping test the release!
SDK 51 beta includes React Native 0.74. The full release notes for SDK 51 won't be available until the stable release, but you can browse the changes in the expo/expo CHANGELOG to learn more about the scope of the release and any breaking changes.
When you create a new project with npx create-expo-app --template default@beta, you will see a renovated new project template! It includes common dependencies and configuration that most projects need, so you can hit the ground running.
You can run npm run reset-project to remove all of the boilerplate code and start fresh.
"Next" Camera and SQLite APIs are now the default. expo-camera/next is now exported from expo-camera, and expo-sqlite/next is now exported from expo-sqlite. You can find the old versions at expo-camera/legacy and expo-sqlite/legacy during SDK 51, and they will be removed in SDK 52.
Beta release of new expo-video library. Following the success of the "next" Camera and SQLite APIs, we are releasing a new video library that incorporates learnings from maintaining expo-av over the years. This library is a complete rewrite of the Video functionality from expo-av, and it's designed to be more reliable and easier to use.
iOS Privacy manifest config field: Beginning on May 1, Apple will require that apps using any "restricted reason" APIs include a privacy manifest. We have added support for the privacy manifest to the Expo config.
New expo-symbols library provides access to the iOS SF Symbols library. This package provides a way to use SF Symbols, a collection of over 5000 icons with multiple weights, scales, and support for animations.
Fingerprint runtime version policy promoted from experimental to beta: By using the "runtimeVersion": { "policy": "fingerprint" } field in your app.json, you can be confident that your updates will always target compatible native runtimes.
ESLint config and npx expo lint command: You can now run npx expo lint in your project to generate an ESLint config file that extends from eslint-config-expo.
Modernized library build.gradle. If you maintain an Expo module, you can apply the changes from this diff.
Bundler speed improvements: EXPO_USE_FAST_RESOLVER=1 can be set to enable up to 6x faster Metro resolution.
Expo CLI supports running on iOS devices over the network and for Vision Pro simulators. Use npx expo run:ios --device to pick a device from the list of available devices on your network.
Expo Orbit for Windows is available in beta. One click to download, install, and run your apps, now for Windows too!
EAS Build default worker image for iOS builds now uses macOS 14.4 and Xcode 15.3
React Native 0.74 and React 18.2.0 (unchanged from SDK 50). Yoga has been upgraded to 3.0, which improves layout correctness and adds support for two additional layout properties. TextEncoder, btoa, atob are now globally available in Hermes.
expo-camera imports have changed: If you want to continue using the legacy implementation, update your imports from expo-camera to expo-camera/legacy. If you were already using the "next" implementation, update the imports from expo-camera/next to expo-camera.
expo-sqlite imports have changed: If you want to continue using the legacy implementation, update your imports from expo-sqlite to expo-sqlite/legacy. If you were already using the "next" implementation, update the imports from expo-sqlite/next to expo-sqlite.
Fingerprint runtime version policy has been renamed: "runtimeVersion": { "policy": "fingerprintExperimental" } → "runtimeVersion": { "policy": "fingerprint" } in your app.json.
The hooks field has been removed from app.json: This was previously used for Classic Updates and sentry-expo, which was deprecated in SDK 50.
sentry-expo is no longer supported, use @sentry/react-native instead. In SDK 50, sentry-expo was deprecated in favor of @sentry/react-native.
Expo Go only supports a single SDK version as of SDK 51.
SDK 51 and React Native 0.74 represent a huge step forward in rolling out the long-awaited New Architecture for React Native.
There is still work to do, but we've made incredible progress so far this year and we think SDK 51 and React Native 0.74 is the time to test your apps with the New Architecture. With your help, we can enable the New Architecture by default in SDK 52.
Most apps will run into some issues when testing with the New Architecture today, but we encourage you to try and report your experience. Improvements will be arriving rapidly during the SDK 51 and React Native 0.74 cycle.
Starting with SDK 51, Expo Go will only support a single SDK version at a time. This means that when the new Expo Go version supporting SDK 51 is released to the App Store and Play Store, it will only support SDK 51. It will not support SDK 50 or below.
The Expo Go app will continue to be a great sandbox to get started quickly and experiment with ideas, but we encourage adopting development builds for a flexible and powerful development environment suitable for real-world applications at scale.
We created expo.dev/go, a website that makes it easy to install a compatible version of Expo Go on your target platform.
Most of the user-facing changes in the latest release of Expo Router are bug fixes and improvements based on feedback from the community. Some notable changes include:
const { "#": hash } = useLocalSearchParams().router.dismiss(), .dismissAll() and .canDismiss()ExpoRequest and ExpoResponse objects in favor of built-in WinterCG-compliant Request/Response objects._layout files (a platform agnostic version is still required).experiments.baseUrl support on web.Found an issue? Report a regression.
Initialize a new project with SDK 51 beta:
npx create-expo-app@latest --template default@betabun create expo-app --template default@betapnpm create expo-app --template default@betayarn create expo-app --template default@betaUpgrade an existing project:
npx expo install expo@next --fixInstall the latest Expo Go for iOS to your physical device:
Install the latest Expo Go for iOS simulators or Android emulators/physical devices:
i or a keyboard shortcut after running npx expo start) and the updated version of Expo Go will be automatically installed.Note: SDK 51 beta is not yet available on Snack.
npm install expo@next or yarn add expo@next, then run npx expo install --fix and consult the Native project upgrade helper and report any issues you encounter.npx expo prebuild --clean and npm run ios and npm run android. Alternatively, try out npx expo run.Thank you for helping us with testing the release — we look forward to shipping it soon!
APR 5, 2024
Xcode 15.3 is now available on EAS Build. You can start using it today by setting your iOS image in eas.json to "image": "latest" or "image": "macos-sonoma-14.3-xcode-15.3".
Note that "latest" is an alias that points to the most recently added image. If you are reading this post long after the publication date, it may point to a different image.
Refer to the build image documentation for more information.
Updated eas.json file that explicitly opts into using Xcode 15.3.
Xcode 15.3 includes SDKs for iOS 17.4, iPadOS 17.4, tvOS 17.4, watchOS 10.4, macOS Sonoma 14.4, and visionOS 1.1. To learn more about the changes introduced in Xcode 15.3 check Apple's official release notes.
If you want to check the full specification of the new image visit our infrastructure docs or check the logs of the Spin up build environment build phase when running a build using the new image.
MAR 29, 2024
Starting on April 29th, 2024, apps uploaded to App Store Connect must be built with Xcode 15 for iOS 17, iPadOS 17, tvOS 17, or watchOS 10. To ensure that your builds are compatible with the upcoming requirements, you can opt-in to use the Xcode 15 for your iOS builds by specifying "image": "macos-sonoma-14.4-xcode-15.3" or "image": "latest" in your eas.json configuration file.
Note that "latest" is an alias that points to the most recently added image. If you are reading this post long after the publication date, it may point to a different image.
Refer to the build image documentation for more information.
Following Apple's announcement we are planning to drop the support for all of the iOS images with Xcode < 15 a month after the required Xcode version changes on Apple's side. This means that starting on May 29th, 2024, we will no longer provide the following images:
macos-monterey-12.1-xcode-13.2macos-monterey-12.3-xcode-13.3macos-monterey-12.4-xcode-13.4macos-monterey-12.6-xcode-14.0macos-monterey-12.6-xcode-14.1macos-monterey-12.6-xcode-14.2macos-ventura-13.3-xcode-14.3macos-ventura-13.4-xcode-14.3.1If you are using one of the images listed above, we recommend updating your configuration to use Xcode 15 as soon as possible to avoid any disruptions in your build process.
JAN 23, 2024 by Evan Bacon
Welcome to Expo Router v3, our most powerful release yet! Today we're introducing beta support for the newest Expo platform: Servers. With this, Expo Router is now the first universal, full-stack React framework!
.mjs support.<Link /> components with the new target, push, and className props.Get started with Expo Router v3 today in one line:
npx create-expo-app@latest -t tabs@50
Note: API Routes are still in beta during SDK 50.
API Routes are a zero-config system for creating server endpoints with a unified build process. Adding a +api.js extension to a route will ensure it's only rendered on the server. API routes are hosted from the same dev server as the website and app in development and must be deployed to a dynamic hosting service in production.
import { ExpoRequest, ExpoResponse } from 'expo-router/server';
export function GET() {
return ExpoResponse.json({ hello: 'world' });
}
export function POST(request: ExpoRequest) {
const { prompt } = await request.json();
// Do something with the prompt
return ExpoResponse.json({
/* ... */
});
}
You can export any of the following functions GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS from an API route. Unsupported methods will automatically return 405: Method not allowed.
The new server architecture will be used to render universal React Server Components in an upcoming release.
To better support API Routes, we've added the ability to perform relative fetch requests on native by setting the production server URL in the app.json:
{
"plugins": [
[
"expo-router",
{
"origin": "https://my-app.dev/"
}
]
]
}
This will enable making relative requests with the fetch API, in both development and production environments:
async function fetchHello() {
// Requests from `http://localhost:8081/hello` in development and `https://my-app.dev/hello` in production.
const response = await fetch('/hello');
const data = await response.json();
// Alerts "Hello world"
alert('Hello ' + data.hello);
}
API Routes are matched after standard routes. To account for API Routes, we've added an official convention to match all 404 / Not Found routes. By creating a +not-found.js route you can match all remaining requests after API routes have been processed. This is supported on all native platforms, and web in server-mode. A 404 status code will also be returned on web.
Expo CLI now supports bundle splitting on async imports (e.g. await import("./route")) when bundling for the web platform. Expo Router automatically splits on routes in the app directory and eagerly loads chunks to prevent network waterfalls on initial requests.
Web-only support is available in Expo Router v3. Support for splitting bundles on native platforms will be included with React Server Component support in the future.
You can now change the /app directory to be any directory in your project. This is useful for testing and white-labeling projects with multiple sub-apps.
{
"plugins": [["expo-router", { "root": "./routes" }]]
}
Avoid changing the root directory as this complicates the build process and may cause unexpected development issues. Opt to use the app and src/app directories instead.
Fonts loaded with expo-font are now automatically extracted and preloaded on web when using static or server output. This enables fonts to start loading before the JavaScript has finished, leading to better initial styles. This system also enables you to statically render your app even if there's a top-level render guard.
import { useFonts } from 'expo-font';
export default function RootLayout() {
// `loaded` will be `true` in static websites as the font was eagerly loaded with the HTML before this JS was executed.
const [loaded] = useFonts({
inter: require('@/fonts/inter.ttf'),
});
if (!loaded) {
// This will no longer be called on static web, meaning the entire boundary will be statically rendered to searchable HTML.
return null;
}
return <Stack />;
}
To fix issues with pushing screens in complex routing scenarios, we've changed the router.push() API to always push new routes, whereas the previous version would pop occasionally. You can use the new router.navigate() API to obtain this previous behavior.
We created a set of Jest utilities that could quickly emulate entire navigation structures.
import { renderRouter, screen } from 'expo-router/testing-library';
it('my-test', async () => {
const MockComponent = jest.fn(() => <View />);
renderRouter(
{
index: MockComponent,
'folder/a': MockComponent,
'(group)/b': MockComponent,
},
{
initialUrl: '/folder/a',
}
);
expect(screen).toHavePathname('/folder/a');
});
The Link component now supports target, rel, and download props on web. Link also now has className support which works as-is on web and can be used with tools like Nativewind to add Tailwind support on all platforms.
<Link target="_blank" className="text-blue-300" href="/home" />
Link components currently navigate to the nearest route matching the href prop. You can now force them to always push a new route by passing the new push prop.
// Navigate to the closest route
<Link href="/" />
// Push "/" as a new route
<Link push href="/" />
npx expo export -p web is over 2x faster for static websites. An average v2 project exported in ~23s, v3 exports in ~11s.
The base JS bundle size for production websites is now 30% smaller (from 1.48mb to 1.05mb). The initial bundle size is further decreased by enabling the new bundle splitting functionality on web.
The URL and URLSearchParams standards are built-in. It was previously necessary to polyfill the web standard URL API. We now ship our own implementation in the expo package, enabling removal of duplicate helper libraries and further reducing bundle size.
In Expo Router v3, we've moved the source code and issue tracking to the expo/expo monorepo. During the migration, we fixed and addressed the majority of issues and bugs regarding Expo Router and added lots more documentation and tests.
Configuration requirements like the Babel plugin have been folded into babel-preset-expo and Expo CLI. Additional Expo Router functionality has been integrated across the SDK with packages like Splash Screen, Linking, and Font.
Expo Router is now more powerful, reliable, and seamless than ever before.
server output mode supports server navigation to dynamic routes on web. Previously, you could only perform client-side navigation to routes like app/[id].tsx.react-refresh. The same Fast Refresh implementation now works across all platforms universally and is far more reliable.experiments.baseUrl. You can now deploy static Expo Router websites to GitHub Pages. This API will be stabilized in SDK 51.mailto: and sms: which don't follow the standard :// convention..mjs modules as expected without modifying the metro.config.js.npx expo customize tsconfig.json.expo-yarn-workspaces to enable monorepo support.npx expo export flag --dump-sourcemap has been renamed to --source-maps. Hermes source maps now work more reliably.paths property in your tsconfig.json to add path aliases. For example, "@/*": ["src/*"] will allow you to write code like import Button from '@/components/Button';.expo-router/babel has been removed. Delete this plugin from your babel.config.js file, and be sure to clear the Metro cache before restarting your dev server.router.push default behavior changed. router.push is now router.navigate and the new router.push will always push routes. This is technically a bug fix, but it may cause unexpected changes in complex navigation behavior.react-native-gesture-handler is no longer added automatically. You can now choose to optionally add gesture handler if you wish to use the <Drawer /> navigator.src directory changed to build. We now ship transpiled JavaScript to production in the expo-router/build/* directory. This is a breaking change if you were imported internals from Expo Router.Here's how to upgrade your app to Expo Router v3 from v2:
Upgrade your app to SDK 50: Follow the instructions in the SDK 50 release notes.
Update the babel.config.js:
expo-router/babel plugin in favor of babel-preset-expo preset.module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
// Remove: plugins: ['expo-router/babel']
};
};
npx expo start --clear
router.push is now router.navigate and the new router.push will always push routes.
react-native-gesture-handler is no longer added automatically and must be injected if you wish to use the <Drawer /> navigator.
Enable Async Routes to use the new bundle splitting functionality on web.
If you have a top-level catch-all route like [...missing].js, rename it to +not-found.js if you plan to use API Routes.
If you have custom splash screen handling, change the import of SplashScreen in expo-router to expo-splash-screen.
If you were using the hrefAttrs prop on the Link component for adding additional web props, migrate to top-level props by the same name.
If you're using the react-native-web style escape hatch to set className on Link components for web, migrate to the top-level className prop.
Ensure you use libraries that are versioned to work with Expo SDK 50:
expo@^50.0.0expo-router@^3.0.0react@18.2.0react-native@~0.73.2react-native-web@~0.19.6@react-navigation/native@^6.0.2You can validate versions automatically with Expo CLI:
npx expo install --check
JAN 18, 2024
Today we're announcing the release of Expo SDK 50. SDK 50 includes React Native 0.73. Thank you to everyone who helped with beta testing.
This API provides a foundation for library authors and adventurous app developers to build browser-based plugins to debug and interact with aspects of their library/app. We built plugins for popular tools: Apollo Client, TanStack Query, TinyBase, React Native Async Storage, and React Navigation — available in the expo/dev-plugins repository.
expo-sqlite/next: a complete re-write of the SQLite library, modernizing the API and bringing it towards parity with web and Node.js equivalents. The API includes both sync and async methods, support for prepared statements, update callbacks, and the Blob data type. SQLite version updated to 3.42.0 on both platforms. A Knex dialect for expo-sqlite is also available.
expo-camera/next: updated to modern native platform best practices for accessing the device camera. For advanced use cases like frame processors, react-native-vision-camera is recommended.
import { CameraView } from 'expo-camera/next';
export default function Camera() {
return (
<CameraView
style={{ flex: 1 }}
/>
);
}
Answers the question: "How do I know if an app JavaScript bundle is compatible with a particular build of my app?"
The @expo/fingerprint CLI or API generates a fingerprint representing the unique native characteristics of a project. If the fingerprint changes, the JavaScript app targeting the older fingerprint may be incompatible.
Usage: npx @expo/fingerprint path/to/your/project
The next major release for universal file-based routing and advanced web support. Includes bugfixes, stability improvements, better documentation, web support, testing, and types. Now has experimental support for building universal server endpoints with API Routes.
--profile flag for eas build:run, eas build:delete command, and improved fully customizable builds previewuseUpdates() hook in the expo-updates package for easy tracking and interaction with updates stateimport { useUpdates } from 'expo-updates';
export default function App() {
const {
currentlyRunning,
availableUpdate,
isUpdateAvailable,
isUpdatePending,
} = useUpdates();
}
use_expo_modules! method now works on tvOS and macOS targets in the Podfileexpo-application, expo-av, expo-constants, expo-device, expo-file-system, expo-font, expo-image, expo-keep-awake, expo-localization, expo-splash-screen, expo-updates, @expo/cliexpo-constants, expo-file-system, expo-keep-awakesentry-expo has been merged into @sentry/react-native@5.16.0, and sentry-expo is now deprecated. The integration with EAS Update is improved: eas update --branch <branch> && npx sentry-expo-upload-sourcemaps dist
getItem and setItem functions, unified Android/iOS behavior. Breaking change: fetching a non-existent value now always returns null"launchModeExperimental": "launcher"npx expo run command: Prompts to select target platform if not specifiednpx expo install --fix now upgrades the expo package to latest patch versionURL and URLSearchParams standards now built-in to the Expo core runtimepnpm or npm --install-mode=isolatedtsconfigPaths enabled in @expo/metro-config by default for path aliasesnpx expo prebuild no longer runs install on each run by default if no dependency changesSDK 47 and 48 projects will no longer work in the latest version of Expo Go. Older versions of Expo Go can be installed for these SDKs.
Expo Go has historically supported multiple SDK versions in a single installation. Starting with SDK 51, each Expo Go release will support only a single SDK version. This change is motivated by the shift toward development builds as the primary development workflow. Expo CLI will continue to automatically install the appropriate Expo Go version for your project's SDK.
Update to the latest version of EAS CLI:
npm i -g eas-cli
Install the new version of the Expo package:
npm install expo@^50.0.0
Upgrade all dependencies to match SDK 50:
npx expo install --fix
Additional upgrade steps:
resolutions/overrides in package.jsonnpx expo-doctor@latest to check for known issuesnpx pod-install if you have an ios directoryJAN 18, 2024
Xcode 15.2 is now available on EAS Build. You can start using it today by setting your iOS image in eas.json to "image": "latest" or "image": "macos-ventura-13.6-xcode-15.2".
Note that "latest" is an alias that points to the most recently added image. If you are reading this post long after the publication date, it may point to a different image.
Refer to the build image documentation for more information.
Xcode 15.2 includes SDKs for iOS 17.2, iPadOS 17.2, tvOS 17.2, watchOS 10.2, macOS Sonoma 14.2, and visionOS. The primary focus of this update is on bug fixes. To learn more about the changes introduced in Xcode 15.2 check Apple's official release notes.
If you want to check the full specification of the new image visit our infrastructure docs or check the logs of the Spin up build environment build phase when running a build using the new image.
DEC 20, 2023
By Jon Samp
2023 began with some audacious goals. We made a long list of new features and capabilities to build. Our goal, in general terms, was to make Expo a more helpful part of developer workflows.
In our all-hands last Thursday our CEO, Charlie Cheever, pulled up that original list and ran through the startling number of new features and capabilities we shipped. There were a few misses for sure. But not many. Our progress in 2023 is something we're all proud of. And as a result of our work it's now easier than ever to create and maintain a universal app with your team.
It's instinctual to want to keep our momentum and run right through the holidays with our eyes on the horizon. And while we're excited about what the future holds (starting with SDK 50 in January!), let's take a moment to appreciate some of the highlights from 2023.
In November we launched Expo Orbit for macOS to make it faster and easier to install and run builds from EAS or elsewhere, and to run Snack projects on simulators and physical devices. It has handy features like opening multiple simulators at once for quicker testing, and even opening Android emulators without audio, which will keep the music you're listening to pitch perfect.
You can download it or install it with homebrew:
brew install expo-orbit
Evan Bacon and his team have been busy bringing the best routing concepts from the web to native iOS and Android apps with Expo Router. Every file in the app directory automatically becomes a route in your mobile navigation, making it easier than ever to build, maintain, and scale your project.
This year we added a lot of new features:
<Head /> component, which supports SSG on web and a ton of truly native functionality on iOS, like automatic handoff, Siri Context, and Quick NotesThe Expo Router V3 Beta opened recently, so check that out if you haven't already.
EAS Build is our hosted service for building app binaries for your Expo and React Native projects. In 2023 we made large strides on EAS Build's feature set with several new performance and workflow improvements.
Here are some of the features we released this year:
eas build:run command.EAS Update is our hosted service for shipping OTA bug fixes in between app store submissions. In 2023 we delivered literal millions of updates, learned from our users, and shipped some key improvements:
For both technical and human reasons this conference was a highlight of the year. It felt great to spend a few days surrounded by hundreds of the best React developers in the world.
At the conference we announced many new features and updates that help teams iterate faster and with more confidence. Appjs Conf 2024 begins accepting CFPs next month and you can still grab early bird ticket prices. We'd love to see you in Poland!
The engineering team at Expo builds and ships product with a combination of speed and quality that sometimes feels impossible. It's hard to pick a handful of highlights and exclude so much of the good work we shipped this year. Here are a few more meaningful 2023 accomplishments:
Thank you to all of the React, React Native, and Expo developers who helped us this year by testing and providing feedback on all the changes we made. Over 250 different developers made contributions in 2023. Your feedback and input meaningfully guide our product direction.
Our goal in 2023 was to improve our open source platform to allow any developer to create genuine native apps. Alongside it, we wanted to make major improvements to our cloud services, EAS, to help developers deliver their code to millions of users. We delivered on those goals.
Next year, we can't wait to go even further. We're thinking hard about how teams work together and test their changes before sending them to users. We're also thinking about how developers can make premier universal experiences that include Android, iOS, and the web.
2024 is going to be a big year for speeding up iterations and making it easier for developers to understand how their apps are doing, react to issues, and consistently deliver the best user experience possible.
DEC 19, 2023
Xcode 15.1 is now available on EAS Build. You can start using it today by setting your iOS image in eas.json to "image": "latest" or "image": "macos-ventura-13.6-xcode-15.1".
Note that "latest" is an alias that points to the most recently added image. If you are reading this post long after the publication date, it may point to a different image.
Refer to the build image documentation for more information.
The primary focus of this update is on bug fixes. To learn more about the changes introduced in Xcode 15.1 check Apple's official release notes.
If you want to check the full specification of the new image visit our infrastructure docs or check the logs of the Spin up build environment build phase when running a build using the new image.