Getting "Failed to resolve plugin for module "expo-community-flipper" only on production build
giacomoalonzi opened this issue · 12 comments
Hello, I'm getting this when I try to build for production with EAS build, even locally.
All works fine for staging or development builds.
[INSTALL_DEPENDENCIES] [4/4] Building fresh packages...
[READ_PACKAGE_JSON] Using package.json:
[READ_PACKAGE_JSON] {
...
[READ_APP_CONFIG]
PluginError: Failed to resolve plugin for module "expo-community-flipper" relative to "/var/folders/86/hpx16y154yvd6kndrx_nxrqc0000gn/T/eas-build-local-nodejs/50a8c532-ea70-4801-8a62-6e3bab46ac2b/build"
I've spent a couple of hours, prebuild is ok but the build don't. Can't figure out why.
Expo SDK 46
eas-cli/2.1.0
expo-cli/6.0.5
Thanks
Hey, thanks for reporting this! Can you share your app.json
? Redactions are okay, I just need to see how the plugin is being included.
This is my config :) thank you!
require('dotenv').config();
import { ExpoConfig, ConfigContext } from '@expo/config';
export default ({ config }: ConfigContext): ExpoConfig => ({
...config,
name: 'My App',
slug: 'myapp',
scheme: 'myapp',
version: '0.14.0',
owner: '---',
orientation: 'portrait',
icon: './assets/icons/1024.png',
userInterfaceStyle: 'automatic',
assetBundlePatterns: ['assets/images/*', 'src/assets/images/*'],
plugins: [
'react-native-email-link',
'expo-community-flipper',
['./plugins/withPladLinkAndroid.js', 'plaid-link-android'],
'sentry-expo',
[
'expo-notifications',
{
color: '#ffffff',
},
],
],
jsEngine: 'hermes',
splash: {
image: './assets/splash.png',
resizeMode: 'contain',
backgroundColor: '#ffffff',
},
runtimeVersion: {
policy: 'sdkVersion',
},
ios: {
jsEngine: 'jsc',
supportsTablet: false,
bundleIdentifier: 'myapp',
buildNumber: '1',
googleServicesFile: process.env.GOOGLE_SERVICES_FILES_IOS_PATH,
associatedDomains: [`applinks:${process.env.UNIVERSAL_LINK_URL}`],
},
android: {
adaptiveIcon: {
backgroundColor: '#FFFFFF',
foregroundImage:
'./assets/icons/res/mipmap-xxxhdpi/liv_adaptive_fore.png',
backgroundImage:
'./assets/icons/res/mipmap-xxxhdpi/liv_adaptive_back.png',
},
package: 'myapp',
versionCode: 6,
allowBackup: false,
googleServicesFile: process.env.GOOGLE_SERVICES_FILES_ANDROID_PATH,
intentFilters: [
{
action: 'VIEW',
autoVerify: true,
data: [
{
scheme: 'https',
host: process.env.UNIVERSAL_LINK_URL,
pathPrefix: '/',
},
{
scheme: 'https',
host: process.env.UNIVERSAL_LINK_URL,
pathPrefix: '/authorization',
},
{
scheme: 'plaid',
host: process.env.UNIVERSAL_LINK_URL,
pathPrefix: '/redirect',
},
{
scheme: 'https',
host: process.env.UNIVERSAL_LINK_URL,
pathPrefix: '/goback',
},
],
category: ['BROWSABLE', 'DEFAULT'],
},
],
},
web: {
favicon: './assets/favicon.png',
config: {
firebase: {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.FIREBASE_APP_ID,
measurementId: process.env.FIREBASE_MEASUREMENT_ID,
},
},
},
extra: {
env: process.env.NODE_ENV,
universalLinkUrl: process.env.UNIVERSAL_LINK_URL,
sentryDns: process.env.SENTRY_DNS,
plaidEnv: process.env.PLAID_ENV,
eas: {
projectId: 'myprojectid',
},
firebase: {
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
measurementId: process.env.FIREBASE_MEASUREMENT_ID,
},
api: {
host: process.env.API_HOST,
},
google: {
expoClientId: process.env.GOOGLE_EXPO_CLIENT_ID,
iosClientId: process.env.GOOGLE_IOS_CLIENT_ID,
androidClientId: process.env.GOOGLE_ANDROID_CLIENT_ID,
webClientId: process.env.GOOGLE_WEB_CLIENT_ID,
secret: process.env.GOOGLE_SECRET,
},
},
hooks: {
postPublish: [
{
file: 'sentry-expo/upload-sourcemaps',
config: {
organization: 'liv-carbon-impact',
project: 'liv-client-app',
authToken: process.env.SENTRY_AUTH_TOKEN,
},
},
],
},
});
Everything looks right, and we didn't change any entry points going from 45-46. A few things I'd double check:
expo-community-flipper
is in your package.json and in the same dependency group asreact-native-email-link
. It's entirely possible EAS is cleaning up dev dependencies at a step in the build and the flipper code gets cleaned up- It works with the flipper plugin commented out (to make sure it's only this plugin
You're right 😅 this is a weird one, especially since the prebuild works... meaning that locally the plugin's working just fine.
Hey @jakobo,
referring to our conversation on Twitter, here is my Podfile, since you asked for it.
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
require File.join(File.dirname(`node --print "require.resolve('@react-native-community/cli-platform-ios/package.json')"`), "native_modules")
require 'json'
podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {}
platform :ios, podfile_properties['ios.deploymentTarget'] || '12.4'
install! 'cocoapods',
:deterministic_uuids => false
target 'voozme' do
use_expo_modules!
config = use_native_modules!
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
# Flags change depending on the env values.
flags = get_default_flags()
use_react_native!(
:path => config[:reactNativePath],
# @generated begin expo-community-flipper-isprod - expo prebuild (DO NOT MODIFY) sync-e002ec08de24fbbe5b9a843ae9231b9627b8b9c4
# https://www.npmjs.com/package/expo-community-flipper
:production => ENV["PRODUCTION"] == "1" ? true : false,
# @generated end expo-community-flipper-isprod
:hermes_enabled => flags[:hermes_enabled] || podfile_properties['expo.jsEngine'] == 'hermes',
:fabric_enabled => flags[:fabric_enabled],
# @generated begin expo-community-flipper-urn - expo prebuild (DO NOT MODIFY) sync-59337f4ef2cee165bd93878dbfd00ddba4d65e67
# https://www.npmjs.com/package/expo-community-flipper
:flipper_configuration => ENV['FLIPPER_DISABLE'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled,
# @generated end expo-community-flipper-urn
# An absolute path to your application root.
:app_path => "#{Dir.pwd}/.."
)
# Uncomment to opt-in to using Flipper
# Note that if you have use_frameworks! enabled, Flipper will not work
#
# if !ENV['CI']
# use_flipper!()
# end
post_install do |installer|
react_native_post_install(installer)
__apply_Xcode_12_5_M1_post_install_workaround(installer)
# This is necessary for Xcode 14, because it signs resource bundles by default
# when building for devices.
installer.target_installation_results.pod_target_installation_results
.each do |pod_name, target_installation_result|
target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
resource_bundle_target.build_configurations.each do |config|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
end
end
end
end
post_integrate do |installer|
begin
expo_patch_react_imports!(installer)
rescue => e
Pod::UI.warn e
end
end
end
My error came out of the blue, after I've upgrade 5 packages. I reverted all of them but 2, the issue does still persist. I am suspecting expo-dev-client 1.3.1
. Since Expo SDK 47 is out now, I will first give this a try as well.
Small update: the plugin does currently not work SDK 47
Small update: the plugin does currently not work SDK 47
Yeah. #38 is tracking the remaining sdk47 changes. In sdk47, it appears the expo prebuild template is no longer coming from main
. We'll also be able to formally depend on expo/config-plugins with a peer dependency on expo instead to help control versioning.
My error came out of the blue, after I've upgrade 5 packages. I reverted all of them but 2, the issue does still persist. I am suspecting expo-dev-client 1.3.1. Since Expo SDK 47 is out now, I will first give this a try as well.
For SDK46, you can use the following strategies to disable Flipper in a production build, completely excising it from your Podfile.
Option 1: app.config.js (forward compatible)
The easiest solution is to switch from app.json
to app.config.js
which gives you access to the node's process.env
. You can then omit the plugin completely based on the existence of an env var. I'm using JS here, but you can also use TypeScript directly by following the expo docs. This creates an opt-in env var for flipper.
// create a plugin configuration w/ blank options that
// is enabeld only if env is set
const expoConfigFlipper =
process.env.FLIPPER === "1"
? [
[
"expo-community-flipper",
{
// config if required
},
],
]
: [];
/** @type {import('@expo/config-types').ExpoConfig} */
const config = {
expo: {
// ...
plugins: [
// other plugins
...expoConfigFlipper,
],
},
};
module.exports = config;
With this configuration, when you run prebuild / build using FIPPER=1 expo prebuild
/ FLIPPER=1 expo build
, the flipper plugin will be loaded. In all other scenarios including a production build, the plugin won't run and the lines won't be included. Going forward for SDK47, this will be the recommended pattern so that EAS users can manage an env value of their choosing and we can remove some of the ruby conditional logic used in the plugin.
Option 2 (<= SDK46) Opt-Out Build
For SDK 45/46, we do have a manual opt-out which you can try with minimal changes. This method also works for app.json
. The configuration supports an ios.enabled
flag which can be explicitly set to false
and disable the flipper integration. The resulting podfile then mirrors the Podfile generated in a react-native bare app.
{
"expo": {
"plugins": [
[
"expo-community-flipper",
{
"ios": {
"enabled": false
}
}
]
]
}
}
Both of the above solutions should be viable for SDK 46, with the config.js option being the forward-looking solution for SDK47. If you make one of these changes, please also include a redacted app.json
so we can see if there's a plugin conflict (for example, react-native firebase forces use_frameworks
and is incompatible with Flipper.
For @hirbod and others, I'm linking #42, which has a similar code smell. If you've removed the plugin completely from app.json
/ app.config.js
and the build is still failing then we have a duplicate bug and it's likely something about how react-native looks for packages as part of autolinking in the Podfile.
It looks like it's possible to make a fix for it: facebook/flipper#2414 (comment)
I'm sorry I'm new to react native and expo so I cannot make the PR.
Thanks @Nek-! These changes are a bit more than I'd like to introduce to the plugin, as manually controlling Flipper's pod dependencies rarely ends well.
To make things worse, the linked comment tested on 0.127.0, and there's been 50 releases since then. :( Our expo integration (#41) will help with some of these issues because it'll be managed inside of the build-properties plugin; the same place where use_frameworks and other troublesome pod code is.
Option 1: app.config.js (forward compatible)
The easiest solution is to switch from
app.json
toapp.config.js
which gives you access to the node'sprocess.env
. You can then omit the plugin completely based on the existence of an env var. I'm using JS here, but you can also use TypeScript directly by following the expo docs. This creates an opt-in env var for flipper.// create a plugin configuration w/ blank options that // is enabeld only if env is set const expoConfigFlipper = process.env.FLIPPER === "1" ? [ [ "expo-community-flipper", { // config if required }, ], ] : []; /** @type {import('@expo/config-types').ExpoConfig} */ const config = { expo: { // ... plugins: [ // other plugins ...expoConfigFlipper, ], }, }; module.exports = config;
Do you think that it will be compatible with the env variables in eas.json?
"cli": {
"version": ">= 3.0.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"env": {
"FLIPPER": "1"
}
},
"development-simulator": {
"developmentClient": true,
"distribution": "internal",
"ios": {
"simulator": true
},
"env": {
"FLIPPER": "1"
}
},
"preview": {
"distribution": "internal"
},
"production": {},
"apk": {
"android": {
"buildType": "apk"
}
}
},
"submit": {
"production": {}
}
}
Do you think that it will be compatible with the env variables in eas.json?
Yes, you can use the EAS env properties to control your app.config.js