Repository navigation
feat: add first-class expo support - #1425
Conversation
|
|
@whydidoo is attempting to deploy a commit to the Callstack Team on Vercel. A member of the Team first needs to authorize it. |
|
@whydidoo can you check the merge conflicts? |
|
lets try and align the Expo package and examples with the workspace catalogs At the moment the new Expo projects use direct pins for React, React Native, Community CLI packages, the React Native Babel preset, React types, TypeScript, and Module Federation, while existing testers use the shared catalog entries. In particular, the Expo apps use React Native 0.86.2 while the catalog is 0.86.0; if 0.86.2 is the Expo 57-compatible version, please update the shared React Native catalog to 0.86.2 and have the relevant examples consume it through the catalog. The Expo SDK packages themselves can live in a dedicated Expo 57 catalog, shared by both Expo fixtures, so their versions do not drift. The same applies to any Expo-specific React, CLI, or Babel compatibility pins that genuinely cannot use the default catalog. regarding typescript version I have a separate pr that updates typescript to v7 which we could merge before this and then update those expo projects to be on v7 as well |
- align Expo 57 fixtures with workspace catalogs and React Native 0.86.2 - tolerate whitespace changes in generated Android and iOS config anchors - stop package manager lookup at package.json workspaces - use Rspack RuleSetRules for Expo Router configuration - add regression coverage for config anchors and workspace detection
MikitasK
left a comment
There was a problem hiding this comment.
excellent work overall 👏 👍
just 2 comments about forwarding custom Expo entry & supporting Rspack 2 cache invalidation, plus 2 non-blocking edge-cases related suggestions:
|
|
Remove repack:release:android and repack:release:ios aliases from tester-expo-widget while keeping the verified host release commands. Document why standalone widget Release currently fails: its config publishes nested lazy chunks as remote files, but the standalone Release resolver expects them inside the installed application. Keep standalone Release support deferred. Preserve the widget's production remote build commands and the remote-in-host workflow validated on Android and iOS.
|
Done, added all three to the Changesets ignore list |
The catalog bump to react-native 0.86.2 left the committed Podfile.lock files of tester-app, tester-federation and tester-federation-v2 pinned to 0.86.0, so every pod install rewrote them. Also picks up the ReactTestApp-Resources pod that tester-federation-v2's app.json resources require.
… with react-native 0.86.2
The expo57 catalog duplicated libraries that the other tester apps already use, at different versions (React 19.2.3 vs 19.2.8, worklets 0.10.1 vs 0.11.3, Module Federation 2.1.0 vs 2.8.0, CLI 20.1.2 vs 20.2.0, and others), so the workspace installed two copies of each. - Keep only Expo packages in the expo57 catalog and bump them to the Expo 57.0.26 release (expo ~57.0.26 plus matching expo-* floors). - Move shared libraries (reanimated, worklets, safe-area-context, screens, async-storage, Module Federation, community CLI) into the testers catalog and point every tester app at it. - Bump react-native and @react-native/* to 0.86.3 across the workspace, matching Expo 57.0.26, and update the Podfile.lock files. - Override react-native-screens to the catalog version: expo-router declares it as a regular dependency, which otherwise resolves a second, newer copy than the native one the apps link. - Derive the Expo host and widget Module Federation requiredVersion values from the installed packages instead of hardcoding them. - Drop the react-native-worklets@0.10.1 packageExtensions patch; 0.11.3 declares those Babel dependencies itself. The shared libraries are slightly ahead of Expo SDK 57's recommended pins; the Expo apps build and run with them on iOS and Android.
The main test matrix runs `pnpm test` on Node.js 18, but the package requires Node.js >=20.19 and Expo's tooling depends on newer APIs (for example `util.parseEnv` in @expo/env), so 10 tests failed there. The test script now reads `engines.node` from package.json and skips with a message on older Node.js versions; otherwise it builds and runs the node:test suite as before.
The owner and EAS projectId tied the tester app to a personal Expo account. Nothing reads them locally (Expo Updates is disabled), and prebuild output is unchanged without them; EAS commands will now ask to link a project instead.
…reset Re.Pack's Babel loader locates hermes-parser through the application's @react-native/babel-preset. Expo applications use babel-preset-expo and don't install that preset, so every module failed to compile with "Failed to import 'hermes-parser'". The repository fixtures hid this because they install the preset. The Expo Babel loader now passes Re.Pack a hermes-parser resolved, in order, through the application's babel-preset-expo (so it follows the Expo SDK), its @react-native/babel-preset, or the hermes-parser bundled with repack-expo (^0.36.0, the version used by React Native 0.86 and babel-preset-expo 57). An application-configured hermesParserPath still takes precedence.
The Expo Babel caller keeps ES modules (supportsStaticESM), so Rspack applied Node's fully-specified ESM resolution to .mjs files and .js files in "type": "module" packages. React Native libraries such as React Navigation and AsyncStorage publish such builds with Metro-style extensionless imports that rely on platform extensions (for example ./useBackButton -> useBackButton.native.js), so they failed with "Module not found". Non-Expo Re.Pack builds transform imports to CommonJS and never hit this; tester-expo didn't either because Expo Router vendors React Navigation. Babel rules configured by ExpoPlugin, including its default rule, now set resolve.fullySpecified to false unless the rule sets it explicitly.
# Conflicts: # pnpm-lock.yaml
|
great work @whydidoo ! |
Summary
This PR introduces first-class Expo support for Re.Pack through a new
@callstack/repack-expopackage.It allows Expo SDK 56 applications using prebuild/CNG to use Rspack and the existing Re.Pack runtime, including ScriptManager and Module Federation v2, without changing the core Re.Pack packages.
The package remains private while we validate the initial integration contract.
What’s included
ExpoPluginfor Rspack that owns the required Expo/Re.Pack defaults:EXPO_PUBLIC_*environment variablesnpx @callstack/repack-expo initnpx @callstack/repack-expo doctorModule Federation v2
Module Federation remains explicit and application-owned, matching regular Re.Pack behavior.
The implementation supports:
React.lazy()chunks alongside remote widgetsRemote widgets cannot provide native dependencies. Native modules must already be installed and linked in the host application.
Native integration
@callstack/repack-expo initonly updates application-owned configuration.Native changes are applied through the Expo Config Plugin during
expo prebuild. The integration does not require users to maintain custom Swift, Kotlin, Gradle or Xcode changes manually.Development applications are launched with:
npm run repack:start npm run repack:ios # or npm run repack:android