Fixing @bacons/apple-targets for Expo SDK 54
Problem
When upgrading from Expo SDK 52 to SDK 54, the @bacons/apple-targets plugin (v3.0.5) breaks during expo prebuild with the following error:
TypeError: config_plugins_1.BaseMods.provider is not a function
This happens because Expo SDK 54 introduced breaking API changes in @expo/config-plugins that moved certain functions from being properties of BaseMods to standalone exports.
TL;DR
Quick fix for @bacons/apple-targets + Expo SDK 54:
- Install:
npm install --save-dev patch-package --legacy-peer-deps
- Add to package.json:
"postinstall": "patch-package"
- Edit
node_modules/@bacons/apple-targets/build/withXcparse.js (see detailed steps below)
- Run:
npx patch-package @bacons/apple-targets
- Test:
npx expo prebuild --clean --platform ios
Full details below ⬇️
Root Cause
In Expo SDK 54's @expo/config-plugins v54.0.2, two critical API changes were made:
BaseMods.provider → Now exported as standalone provider from createBaseMod module
BaseMods.withGeneratedBaseMods → Now exported as standalone withGeneratedBaseMods from createBaseMod module
The @bacons/apple-targets plugin (as of v3.0.5) still uses the old SDK 52/53 API, calling:
config_plugins_1.BaseMods.provider({...})
config_plugins_1.BaseMods.withGeneratedBaseMods(config, {...})
These function calls fail because they no longer exist on the BaseMods object.
Prerequisites
Before applying this fix, ensure:
If you don't have these, this fix may not apply to your situation.
Solution: patch-package
Since there's no official SDK 54-compatible version of @bacons/apple-targets yet, we use patch-package to fix the plugin locally. This approach:
✅ Persists across npm install runs
✅ Works with Expo's Continuous Native Generation (CNG)
✅ Doesn't require forking the plugin
✅ Can be easily removed once official fix is released
Step-by-Step Fix
1. Install patch-package
npm install --save-dev patch-package --legacy-peer-deps
Note: Use --legacy-peer-deps if you encounter React version conflicts (SDK 54 uses React 19).
2. Add postinstall script
Edit your package.json to add the postinstall hook:
{
"scripts": {
"postinstall": "patch-package"
}
}
3. Apply the fix to node_modules
Edit node_modules/@bacons/apple-targets/build/withXcparse.js:
Add this import after the existing imports (around line 30):
const createBaseMod_1 = require("@expo/config-plugins/build/plugins/createBaseMod");
Find and replace (around line 42):
// BEFORE: ❌
return config_plugins_1.BaseMods.withGeneratedBaseMods(config, {
// AFTER: ✅
return (0, createBaseMod_1.withGeneratedBaseMods)(config, {
Find and replace (around line 47):
// BEFORE: ❌
[customModName]: config_plugins_1.BaseMods.provider({
// AFTER: ✅
[customModName]: (0, createBaseMod_1.provider)({
4. Generate the patch file
npx patch-package @bacons/apple-targets
This creates patches/@bacons+apple-targets+3.0.5.patch in your project root.
5. Test the fix
npx expo prebuild --clean --platform ios
The prebuild should now succeed without errors.
Success looks like:
✔ Created native directories | iOS, Android
✔ Updated Info.plist
✔ Updated Podfile
✔ Installing CocoaPods dependencies
✔ Your widget targets appear in the Xcode project
If you see these, the patch worked! 🎉
The Patch File
The complete patch file (patches/@bacons+apple-targets+3.0.5.patch) looks like this:
diff --git a/node_modules/@bacons/apple-targets/build/withXcparse.js b/node_modules/@bacons/apple-targets/build/withXcparse.js
index 36e2ccb..000a537 100644
--- a/node_modules/@bacons/apple-targets/build/withXcparse.js
+++ b/node_modules/@bacons/apple-targets/build/withXcparse.js
@@ -27,6 +27,7 @@ exports.withXcodeProjectBetaBaseMod = exports.withXcodeProjectBeta = void 0;
const xcode_1 = require("@bacons/xcode");
const xcodeParse = __importStar(require("@bacons/xcode/json"));
const config_plugins_1 = require("@expo/config-plugins");
+const createBaseMod_1 = require("@expo/config-plugins/build/plugins/createBaseMod");
const fs = __importStar(require("fs"));
const customModName = "xcodeProjectBeta2";
const withXcodeProjectBeta = (config, action) => {
@@ -38,13 +39,13 @@ const withXcodeProjectBeta = (config, action) => {
};
exports.withXcodeProjectBeta = withXcodeProjectBeta;
const withXcodeProjectBetaBaseModInternal = (config) => {
- return config_plugins_1.BaseMods.withGeneratedBaseMods(config, {
+ return (0, createBaseMod_1.withGeneratedBaseMods)(config, {
platform: "ios",
saveToInternal: true,
skipEmptyMod: false,
providers: {
// Append a custom rule to supply AppDelegate header data to mods on `mods.ios.AppClipInfoPlist`
- [customModName]: config_plugins_1.BaseMods.provider({
+ [customModName]: (0, createBaseMod_1.provider)({
isIntrospective: false,
// isIntrospective: true,
async getFilePath({ modRequest, _internal }) {
Verification
After applying the patch, you should see:
- ✅
expo prebuild completes without errors
- ✅ iOS project includes your widget extension targets
- ✅ CocoaPods installation succeeds
- ✅ iOS build compiles successfully
Tested Scenarios
This fix has been verified to work with:
- ✅ iOS widgets (multiple widget types + Live Activities)
- ✅ Expo development builds
- ✅ Multiple widget targets in a single project
- ✅ CocoaPods installation
- ✅ Production iOS builds
Note: This patch specifically addresses the prebuild phase. If you encounter runtime widget issues, those are separate from this fix.
Troubleshooting
Patch doesn't apply
- Error:
patch-package: ERROR: Failed to apply patch
- Solution: Delete
node_modules and reinstall, then try again
- Check: Ensure you have
@bacons/apple-targets version 3.0.5 exactly
Still getting "provider is not a function"
- Check 1: Verify patch file exists:
patches/@bacons+apple-targets+3.0.5.patch
- Check 2: Confirm postinstall script ran:
npm run postinstall manually
- Check 3: Clear Metro cache:
npx expo start -c
- Check 4: Delete
node_modules and ios folder, reinstall everything
Different version of @bacons/apple-targets
- This patch is for v3.0.5 specifically
- For other versions, the line numbers may differ
- Check the actual file and adjust the patch accordingly
- You may need to create your own patch following the same pattern
Prebuild succeeds but widgets don't show up
- This fix only addresses the prebuild error
- Widget runtime issues are separate - check your widget code and entitlements
- Ensure your App Group is correctly configured
Why This Happens
Expo SDK 54 represents a major upgrade that includes:
- React Native 0.81.4
- React 19.1.0
- Significant internal API refactoring in
@expo/config-plugins
The @expo/config-plugins team moved some internal APIs to improve modularity. While this is good for long-term maintainability, it breaks plugins that relied on the old API structure.
Alternative Approaches Considered
1. Manual Xcode Integration
Rejected because Expo's Continuous Native Generation (CNG) wipes out manual changes on every expo prebuild --clean.
2. Wait for Official Fix
Rejected because users already rely on widgets. There's no timeline for an official SDK 54-compatible release.
3. Fork and Maintain Plugin
Considered but patch-package is simpler and easier to remove once the official fix arrives.
4. Downgrade to SDK 53
Rejected because it would lose all SDK 54 upgrade work and delay access to new features.
When to Remove This Patch
Remove the patch when:
@bacons/apple-targets releases an SDK 54-compatible version, OR
- You migrate to a different widget solution, OR
- Expo provides native widget support
To remove:
rm patches/@bacons+apple-targets+3.0.5.patch
npm install @bacons/apple-targets@latest
Related Issues
Contributing Back
If this fix helps you, consider:
- Testing it thoroughly with your widget implementation
- Reporting your success/issues on the @bacons/apple-targets repo
- Offering to submit a PR with this fix
- Sharing your experience to help others encountering the same issue
Credits
This fix was discovered and tested by Adebayo Adebisi (@adebayoadebisi) during a production app upgrade from Expo SDK 52 to SDK 54, where maintaining iOS widget functionality was critical for existing users.
Special thanks to the Expo and @bacons/apple-targets communities for their excellent tooling.
Last Updated: October 2025
Tested With:
- Expo SDK 54.0.13
- @bacons/apple-targets 3.0.5
- @expo/config-plugins 54.0.2
- React Native 0.81.4
- React 19.1.0
- Xcode 26.0.1
Fixing @bacons/apple-targets for Expo SDK 54
Problem
When upgrading from Expo SDK 52 to SDK 54, the
@bacons/apple-targetsplugin (v3.0.5) breaks duringexpo prebuildwith the following error:This happens because Expo SDK 54 introduced breaking API changes in
@expo/config-pluginsthat moved certain functions from being properties ofBaseModsto standalone exports.TL;DR
Quick fix for
@bacons/apple-targets+ Expo SDK 54:npm install --save-dev patch-package --legacy-peer-deps"postinstall": "patch-package"node_modules/@bacons/apple-targets/build/withXcparse.js(see detailed steps below)npx patch-package @bacons/apple-targetsnpx expo prebuild --clean --platform iosFull details below ⬇️
Root Cause
In Expo SDK 54's
@expo/config-pluginsv54.0.2, two critical API changes were made:BaseMods.provider→ Now exported as standaloneproviderfromcreateBaseModmoduleBaseMods.withGeneratedBaseMods→ Now exported as standalonewithGeneratedBaseModsfromcreateBaseModmoduleThe
@bacons/apple-targetsplugin (as of v3.0.5) still uses the old SDK 52/53 API, calling:config_plugins_1.BaseMods.provider({...})config_plugins_1.BaseMods.withGeneratedBaseMods(config, {...})These function calls fail because they no longer exist on the
BaseModsobject.Prerequisites
Before applying this fix, ensure:
@bacons/apple-targetsv3.0.5 installedBaseMods.provider is not a functionerrorIf you don't have these, this fix may not apply to your situation.
Solution: patch-package
Since there's no official SDK 54-compatible version of
@bacons/apple-targetsyet, we usepatch-packageto fix the plugin locally. This approach:✅ Persists across
npm installruns✅ Works with Expo's Continuous Native Generation (CNG)
✅ Doesn't require forking the plugin
✅ Can be easily removed once official fix is released
Step-by-Step Fix
1. Install patch-package
Note: Use
--legacy-peer-depsif you encounter React version conflicts (SDK 54 uses React 19).2. Add postinstall script
Edit your
package.jsonto add the postinstall hook:{ "scripts": { "postinstall": "patch-package" } }3. Apply the fix to node_modules
Edit
node_modules/@bacons/apple-targets/build/withXcparse.js:Add this import after the existing imports (around line 30):
Find and replace (around line 42):
Find and replace (around line 47):
4. Generate the patch file
This creates
patches/@bacons+apple-targets+3.0.5.patchin your project root.5. Test the fix
The prebuild should now succeed without errors.
Success looks like:
If you see these, the patch worked! 🎉
The Patch File
The complete patch file (
patches/@bacons+apple-targets+3.0.5.patch) looks like this:Verification
After applying the patch, you should see:
expo prebuildcompletes without errorsTested Scenarios
This fix has been verified to work with:
Note: This patch specifically addresses the prebuild phase. If you encounter runtime widget issues, those are separate from this fix.
Troubleshooting
Patch doesn't apply
patch-package: ERROR: Failed to apply patchnode_modulesand reinstall, then try again@bacons/apple-targetsversion 3.0.5 exactlyStill getting "provider is not a function"
patches/@bacons+apple-targets+3.0.5.patchnpm run postinstallmanuallynpx expo start -cnode_modulesandiosfolder, reinstall everythingDifferent version of @bacons/apple-targets
Prebuild succeeds but widgets don't show up
Why This Happens
Expo SDK 54 represents a major upgrade that includes:
@expo/config-pluginsThe
@expo/config-pluginsteam moved some internal APIs to improve modularity. While this is good for long-term maintainability, it breaks plugins that relied on the old API structure.Alternative Approaches Considered
1. Manual Xcode Integration
Rejected because Expo's Continuous Native Generation (CNG) wipes out manual changes on every
expo prebuild --clean.2. Wait for Official Fix
Rejected because users already rely on widgets. There's no timeline for an official SDK 54-compatible release.
3. Fork and Maintain Plugin
Considered but patch-package is simpler and easier to remove once the official fix arrives.
4. Downgrade to SDK 53
Rejected because it would lose all SDK 54 upgrade work and delay access to new features.
When to Remove This Patch
Remove the patch when:
@bacons/apple-targetsreleases an SDK 54-compatible version, ORTo remove:
Related Issues
Contributing Back
If this fix helps you, consider:
Credits
This fix was discovered and tested by Adebayo Adebisi (@adebayoadebisi) during a production app upgrade from Expo SDK 52 to SDK 54, where maintaining iOS widget functionality was critical for existing users.
Special thanks to the Expo and @bacons/apple-targets communities for their excellent tooling.
Last Updated: October 2025
Tested With: